Why does my AutoValueExtension annotation not work? - annotations

I have been trying to use Square's Redacted annotation to redact a pin from a toString() method in my auto generated class but the extension is not being applied. It seems like the extension is not read by the class loader.
The #AutoValue annotation works fine but the #Redacted annotation is not applied.
package io.*******.********.order.pin.hsm;
import com.google.auto.value.AutoValue;
import io.*****.crypto.model.PinBlockFormat;
#AutoValue
public abstract class GeneratePvvRequest {
/** #return Hexadecimal string representing the encrypted PIN */
#Redacted
public abstract String pinBlock();
/** #return Account number under which the PIN block is currently encrypted */
public abstract String pinBlockAccountNumber();
/** #return Name of the ZPK under which the PIN block is currently encrypted */
public abstract String zpkName();
/** #return Index of the ZPK under which the PIN block is currently encrypted */
public abstract Integer zpkIndex();
/** #return ISO format under which the PIN block is currently encrypted */
public abstract PinBlockFormat pinBlockFormat();
/** #return Account number used to generate the pin's PVV */
public abstract String pvvAccountNumber();
public static GeneratePvvRequest create(
String pinBlock,
String pinBlockAccountNumber,
String zpkName,
Integer zpkIndex,
PinBlockFormat pinBlockFormat,
String pvvAccountNumber) {
return new AutoValue_GeneratePvvRequest(
pinBlock,
pinBlockAccountNumber,
zpkName,
zpkIndex,
pinBlockFormat,
pvvAccountNumber);
}
}

I discovered my problem. I needed to add an annotationProcessorPath to the maven-compiler-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<annotationProcessorPaths>
<!-- Allow Dagger to generate its boilerplate -->
<path>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>${electrum.dependency.dagger.version}</version>
</path>
<!-- The below wasn't strictly required, but adding any entries under annotationProcessorPaths -->
<!-- overrides the default path which included the necessary annotation processor for auto-value -->
<path>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<version>${electrum.dependency.auto-value.version}</version>
</path>
<path>
<groupId>com.squareup.auto.value</groupId>
<artifactId>auto-value-redacted</artifactId>
<version>1.1.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Everything works hunky-dory now.

Related

Magento2: add custom quote extension attribute

I am trying to add an extension attribute to a quote through a custom REST API, and I would like to retrieve this info later.
But when I try to get the value, is always null.
The code will explain better than me.
etc/di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
[...]
<preference for="Wow\Orderplatform\Api\Data\CartInterface"
type="Wow\Orderplatform\Model\Cart" />
</config>
etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\CartInterface">
<attribute code="order_platform" type="Wow\Orderplatform\Api\Data\CartInterface"/>
</extension_attributes>
</config>
CartInterface
interface CartInterface extends ExtensibleDataInterface
{
const ORDER_PLATFORM = 'order_platform';
/**
* Retrieve order platform
*
* #return string
*/
public function getOrderPlatform();
/**
* Set order platform
*
* #param string $orderPlatform
* #return $this
*/
public function setOrderPlatform($orderPlatform);
}
The implementation:
class Cart extends AbstractExtensibleModel implements CartInterface
{
/**
* {inheritdoc}
*/
public function getOrderPlatform()
{
return $this->getData(self::ORDER_PLATFORM);
}
/**
* {inheritdoc}
*/
public function setOrderPlatform($orderPlatform)
{
return $this->setData(self::ORDER_PLATFORM, $orderPlatform);
}
}
I try to save the extension attribute in a REST API:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$platformExt = $this->wowCartExtInterfaceFactory->create();
$platformExt->setOrderPlatform($platform);
$extensions->setOrderPlatform($platformExt);
$quote->setExtensionAttributes($extensions);
$this->quoteRepository->save($quote);
No errors in this procedure.
The problem is that I am not able to get back the value from the quote:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$extensions->getOrderPlatform(); // Always null
Any hints?
Thanks
This is core bug in magento2 tried to do same for some requirement and found
Join extension attributes are not adding to quote results
There seems to be an issue with join extension attributes as per my debugging
ex.
<extension_attributes for="Magento\Quote\Api\Data\CartItemInterface">
<attribute code="original_catalog_price" type="Magento\NegotiableQuote\Api\Data\NegotiableQuoteItemInterface" >
<join reference_table="negotiable_quote_item" reference_field="quote_item_id" join_on_field="item_id">
<field>original_catalog_price</field>
</join>
</attribute>
</extension_attributes>
Hopefully, the patch will release soon.

Aspectj: intercept method from external jar

I am using a X.jar and adding to my AspectJ project(in eclipse). I have written pointcut and advice for a method myMethod() inside X.jar.
But aspectj is not intercepting this method call.
How can I tell aspectj to intercept method calls on external jars.Or is it not possible?
Thanks
There are two options:
a) compile the aspects into the JAR
b) use load time weaving (I'd go with that one)
Both of these are advanced topics, I'd suggest you read AspectJ in Action (2nd Ed) by Ramnivas Laddad to learn more.
To clarify: there are different types of pointcuts. If your code calls the library's methods, you can of course intercept these calls, as they happen in your code. So call() pointcuts will work, but execute() (and many other) pointcuts won't because they change the executing method, which is not in your code base. So you have to either change the byte code of the library (option a) or change how it is loaded into your application (option b).
Here is a simple example with AspectJ Load-Time Weaving on GitHub https://github.com/medvedev1088/aspectj-ltw-example
It uses Joda Time library to demonstrate how to intercept the DateTime#toString() method invocations.
The aspect:
#Aspect
public class DateTimeToStringAspect {
public static final String TO_STRING_RESULT = "test";
#Pointcut("execution(* org.joda.time.base.AbstractDateTime.toString())")
public void dateTimeToString() {
}
#Around("dateTimeToString()")
public Object toLowerCase(ProceedingJoinPoint joinPoint) throws Throwable {
Object ignoredToStringResult = joinPoint.proceed();
System.out.println("DateTime#toString() has been invoked: " + ignoredToStringResult);
return TO_STRING_RESULT;
}
}
aop.xml
<aspectj>
<aspects>
<!-- Aspects -->
<aspect name="com.example.aspectj.DateTimeToStringAspect"/>
</aspects>
<weaver options="-verbose -showWeaveInfo">
<include within="org.joda.time.base.AbstractDateTime"/>
</weaver>
</aspectj>
test:
public class DateTimeToStringAspectTest {
#Test
public void testDateTimeToString() throws Exception {
assertThat(new DateTime().toString(), is(DateTimeToStringAspect.TO_STRING_RESULT));
}
}
Surefire plugin configuration from pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
<argLine>-javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectjweaver.version}/aspectjweaver-${aspectjweaver.version}.jar</argLine>
</configuration>
</plugin>

javax.ws.rs.core.PathSegment and Errai

Errai has support for JAX-RS, although when I tried to use it with the supplied Maven archetype GWT complained with the error:
No source code is available for type javax.ws.rs.core.PathSegment; did you forget to inherit a required module?
The PathSegment interface appears to be part of the official Java EE standard, so why is this class not available?
A solution is to create the javax.ws.rs.core package in your GWT project, and include the interfaces for yourself. These interfaces are MultivaluedMap:
package javax.ws.rs.core;
import java.util.List;
import java.util.Map;
/**
* A map of key-values pairs. Each key can have zero or more values.
*
*/
public interface MultivaluedMap<K, V> extends Map<K, List<V>> {
/**
* Set the key's value to be a one item list consisting of the supplied value.
* Any existing values will be replaced.
*
* #param key the key
* #param value the single value of the key
*/
void putSingle(K key, V value);
/**
* Add a value to the current list of values for the supplied key.
* #param key the key
* #param value the value to be added.
*/
void add(K key, V value);
/**
* A shortcut to get the first value of the supplied key.
* #param key the key
* #return the first value for the specified key or null if the key is
* not in the map.
*/
V getFirst(K key);
}
PathSegment:
package javax.ws.rs.core;
/**
* Represents a URI path segment and any associated matrix parameters. When an
* instance of this type is injected with {#link javax.ws.rs.PathParam}, the
* value of the annotation identifies which path segment is selected and the
* presence of an {#link javax.ws.rs.Encoded} annotation will result in an
* instance that supplies the path and matrix parameter values in
* URI encoded form.
*
* #see UriInfo#getPathSegments
* #see javax.ws.rs.PathParam
*/
public interface PathSegment
{
/**
* Get the path segment.
* <p/>
*
* #return the path segment
*/
String getPath();
/**
* Get a map of the matrix parameters associated with the path segment.
* The map keys are the names of the matrix parameters with any
* percent-escaped octets decoded.
*
* #return the map of matrix parameters
* #see Matrix URIs
*/
MultivaluedMap<String, String> getMatrixParameters();
}
You'll need a GWT module file (in the javax.ws.rs package):
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6//EN"
"http://google-web-toolkit.googlecode.com/svn/releases/1.6/distro-source/core/src/gwt-module.dtd">
<module rename-to="App">
<source path="core"/>
</module>
And you'll need to add an inherits reference to you application GWT module:
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6//EN"
"http://google-web-toolkit.googlecode.com/svn/releases/1.6/distro-source/core/src/gwt-module.dtd">
<module rename-to="App">
<inherits name='com.google.gwt.user.User'/>
<inherits name="org.jboss.errai.common.ErraiCommon"/>
<inherits name="org.jboss.errai.ioc.Container"/>
<inherits name="org.jboss.errai.enterprise.Jaxrs"/>
<inherits name="com.redhat.topicindex.rest"/>
<inherits name="javax.ws.rs.core"/>
</module>

Having a map as a Maven plugin parameter

I am using maven 3 and I want to pass in a type Map as a parameter.
I have this in my mojo at the moment:
/**
* #parameter expression="${rep.env}" alias="environments"
* #required
*/
private Map<String,String[]> environments = null;
I am passing in this during the configuration:
<environments>
<Testing>
<param>
unit
</param>
</Testing>
</environments>
It is complaining that it is missing the parameter environments, are you allowed to do this in maven?
Did you try to just remove the alias="environments" attribute?
Another point is that I am not sure that Maven will allow you to set a Map of String[] as key. I think it will only deal with Map<String, String> (the page here only shows a basic Map example).
Eventually, what you can do is to allow comma-separated value instead of a String[]:
<configuration>
<environments>
<one>a,b,c</one>
<two>d</two>
</environments>
</configuration>
and then, when you have to deal with your values, you simply split your String to get a String array (you can use Apache Commons-lang StringUtils to do that easily):
/**
* #parameter expression="${rep.env}"
* #required
*/
private Map<String, String> environments = null;
public void foo() {
String[] values = StringUtils.split(environments.get("one"), ',');
// values == {"a", "b", "c"};
}

Struts 2 JUnit Plugin v2.2.3: Test Class Extending StrutsTestCase; 'request' is null

I am attempting to use the Struts2 JUnit Plugin (v2.2.3 w/ Struts2 v2.2.3) and have run into several issues.
I attempted to use the Struts2 JUnit Plugin Tutorial as a guide. The first change I needed to make (not in the guide) is to annotate my test class with:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath*:applicationContext-test.xml"})
because I was getting the error when trying to run my unit test:
SEVERE: [56:51.239] ********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********
Looks like the Spring listener was not configured for your web app!
Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.
You might need to add the following to web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
SEVERE: [56:51.254] Dispatcher initialization failed
This is different than the tutorial- does anyone know why I needed to do this?
I also had to add the following Spring Jars (I have the necessary Struts2 jars included in my classpath):
spring-beans-2.5.6.jar
spring-context-2.5.6.jar
spring-core-2.5.6.jar
spring-test-2.5.6.jar
spring-web-2.5.6.jar
I do not use Spring w/in my struts app, but I assume these jars are needed to use the mock request object and such in the StrutsTestCase.
My Test class:
package com.actions;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import org.apache.struts2.StrutsTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.beans.LabelValueBean;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath*:applicationContext-test.xml"})
public class DocumentCategoryTest extends StrutsTestCase {
private static Logger log = Logger.getLogger(DocumentCategoryTest .class);
/**
* Testing RetrieveDocumentTypesForDocumentCategory
* Expecting the List<LabelValueBean> is not null
* #throws ServletException
* #throws UnsupportedEncodingException
*/
#Test
public void testRetrieveDocumentTypesForDocumentCategory() throws UnsupportedEncodingException, ServletException {
final String docCategory = "Employment";
//set parameters
request.setParameter("documentCategoryDescription", docCategory);
//execute the action
executeAction("/recipient/RetrieveDocumentTypesForDocumentCategory.action");
//retrieve the document types
#SuppressWarnings("unchecked")
List<LabelValueBean> testDocTypeList = (List<LabelValueBean>) findValueAfterExecute("documentTypes");
//make sure the document type list is not null and has at least one document type
assertNotNull(testDocTypeList);
assertTrue("At least one document type should exist for category 'Employment'", testDocTypeList.size() > 0);
//print types
log.debug("Document types for category '" + docCategory + "'");
log.debug(testDocTypeList);
}
}
When I execute the action, I get a NullPointerException on the request.setParameter piece of code:
java.lang.NullPointerException
at com.actions.DocumentCategoryTest.testRetrieveDocumentTypesForDocumentCategory(DocumentCategoryTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:160)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:160)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
This is because, for some reason, request is null in StrutsTestCase. Why is this? I'm doing exactly as the tutorial dictates!
My action class extends another class (BaseAction) that extends ActionSupport and implements SessionAware.
package com.actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.actions.BaseAction;
/**
* Retrieves the document types for the passed in document category
*/
public class DocumentIndexingData extends BaseAction {
private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(DocumentIndexingData.class);
/*=========================================================================
* FIELDS
*=========================================================================*/
/**
* The description to use to look up the document types for that category
*/
private String documentCategoryDescription;
/**
* List of document types for a category
*/
private List<LabelValueBean> documentTypes;
/*=========================================================================
* PUBLIC METHODS
*=========================================================================*/
/**
* Retrieves & sets list of document types for document category with passed in ID
*
* #return If there is an error, document type will be set to ERROR; SUCCESS is always returned by this method
*/
public String retrieveDocumentTypesForDocumentCategory() {
List<LabelValueBean> docTypes = new ArrayList<LabelValueBean>();
//retrieve document types for passed in category ID
log.debug("looking up document types for category: " + getDocumentCategoryDescription());
////////////////
//retrieve the document types for the document category here...
////////////////
this.setDocumentTypes(docTypes);
log.debug("document types found: " + getDocumentTypes());
return SUCCESS;
}
/*=========================================================================
* GETTERS/SETTERS
*=========================================================================*/
/**
* Retrieves the list of document types
*
* #return list of document types
*/
public List<LabelValueBean> getDocumentTypes() {
return documentTypes;
}
/**
* Sets the list of document types
*
* #param documentTypes
*/
public void setDocumentTypes(List<LabelValueBean> documentTypes) {
this.documentTypes = documentTypes;
}
/**
* Retrieves the document category to retrieve document types for
*
* #return the document category
*/
public String getDocumentCategoryDescription() {
return documentCategoryDescription;
}
/**
* Sets the document category to retrieve document types for
*
* #param documentCategoryDescription the document category to retrieve document types for
*/
public void setDocumentCategoryDescription(String documentCategoryDescription) {
this.documentCategoryDescription = documentCategoryDescription;
}
}
struts.xml entry:
<!-- indexing attributes action -->
<action name="RetrieveDocumentTypesForDocumentCategory" class="com.actions.DocumentIndexingData" method="retrieveDocumentTypesForDocumentCategory">
<result type="json">
<param name="root">documentTypes</param>
</result>
</action>
I'm following the tutorial pretty closely, why is request null? Thank you so much for any help!
UPDATE (My Solution! via #Alex):
I now only have the following Struts JARs included on my classpath:
struts2-junit-plugin-2.2.3.jar
spring-beans-2.5.6.jar
spring-context-2.5.6.jar
spring-core-2.5.6.jar
spring-test-2.5.6.jar
spring-web-2.5.6.jar
Sample test:
public class MyTest extends StrutsTestCase {
#Test
public void testMyAction() throws Exception {
request.setParameter("aParameter", "aValue");
//create action proxy
ActionProxy proxy = getActionProxy("/test/MyAction");
assertNotNull(proxy);
MyAction action = (MyAction) proxy.getAction();
assertNotNull(action);
//execute the action
String result = proxy.execute();
//make assertions, expecting success and no error messags
assertTrue("There should be no field errors: " + action.getFieldErrors(), action.getFieldErrors().size() == 0);
assertTrue("There should be no action errors: " + action.getActionErrors(), action.getActionErrors().size() == 0);
assertEquals("Result did not match expected value; ", Action.SUCCESS, result);
}
}
I do not use Spring w/in my struts app, but I assume these jars are needed to use the mock request object and such in the StrutsTestCase.
Given the exception messages you're seeing above your application believes that it uses Spring. Do you have the Struts2-Spring-Plugin on your classpath? If you're not using Spring for IoC then you shouldn't include it on your classpath.
You should be able to test your actions by following guide you've referenced without any spring jars if you don't use Spring. Try removing all the spring jars and the struts2-spring-plugin jar. You also certainly don't need:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath*:applicationContext-test.xml"})
in your test class if you don't use spring.
Also check that your struts.xml doesn't contain this line:
<constant name="struts.objectFactory"
value="org.apache.struts2.spring.StrutsSpringObjectFactory"/>