Lambda Error: #DynamoDBIndexHashKey must specify one of HASH GSI name/names - amazon-web-services

I have the following class:
#DynamoDBTable(tableName = "PodcastReviewService-Episodes")
public class Episode {
private String podcast;
private int episodeNr;
private String name;
private int avgRating;
private String episodeId;
private List<Review> reviews;
public Episode() {}
#DynamoDBIndexHashKey(attributeName = "podcast")
public String getPodcast() {return podcast;}
#DynamoDBRangeKey(attributeName = "episodeNr")
public int getEpisodeNr() {return episodeNr;}
#DynamoDBAttribute(attributeName = "name")
public String getName() {
return name;
}
#DynamoDBIndexHashKey(attributeName = "avgRating", globalSecondaryIndexName = "avgRating")
public int getAvgRating() {
return avgRating;
}
#DynamoDBIndexRangeKey(attributeName = "episodeId", globalSecondaryIndexName = "episodeId")
public String getEpisodeId() {
return episodeId;
}
#DynamoDBAttribute(attributeName = "reviews")
public List<Review> getReviews() {
return reviews;
}
The class that attempts to add an object Episode to my DynamoDB table is :
public class EpisodeDao {
private final DynamoDBMapper dynamoDBMapper;
public EpisodeDao() {
this.dynamoDBMapper = new DynamoDBMapper(AmazonDynamoDBClientBuilder.standard().withCredentials(DefaultAWSCredentialsProviderChain.getInstance()).withRegion(Regions.US_WEST_2).build());
}
public Episode getEpisode(String podcast, int episodeNr) {
Episode episode = this.dynamoDBMapper.load(Episode.class, podcast, episodeNr);
if (episode == null) {
throw new EpisodeNotFoundException("Could not find episode of " + podcast + " nr." + episodeNr);
}
return episode;
}
public Episode saveEpisode(String podcast, String name, int episodeNr) {
Episode episode = new Episode();
//Check if episode already exists, if so return an DuplicateEpisodeException
//We initialize average rating at 0 since no reviews have been submitted
if (getEpisode(podcast, episodeNr) == null) {
episode.setPodcast(podcast);
episode.setName(name);
episode.setEpisodeNr(episodeNr);
episode.setEpisodeId(podcast.charAt(0) + name.charAt(0) + PodcastReviewsUtils.generateRandomID());
episode.setAvgRating(0);
episode.setReviews(new ArrayList<>());
} else throw new DuplicateEpisodeException("The episode that you are trying to add seems to already exist.");
return episode;
}
This is the output I get on Lambda:
"errorMessage": "#DynamoDBIndexHashKey must specify one of HASH GSI name/names",
"errorType": "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException",
"stackTrace": [
"com.amazonaws.services.dynamodbv2.datamodeling.StandardAnnotationMaps$FieldMap.globalSecondaryIndexNames(StandardAnnotationMaps.java:345)",
"com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel$Properties$Immutable.<init>(DynamoDBMapperFieldModel.java:459)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$Bean.<init>(StandardBeanProperties.java:92)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$Bean.<init>(StandardBeanProperties.java:86)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.putOrFlatten(StandardBeanProperties.java:217)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.putAll(StandardBeanProperties.java:207)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.<init>(StandardBeanProperties.java:198)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$CachedBeans.getBeans(StandardBeanProperties.java:55)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$CachedBeans.access$100(StandardBeanProperties.java:48)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties.of(StandardBeanProperties.java:42)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$TableBuilder.<init>(StandardModelFactories.java:132)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$TableBuilder.<init>(StandardModelFactories.java:116)",
"com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$StandardTableFactory.getTable(StandardModelFactories.java:107)",
"com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.getTableModel(DynamoDBMapper.java:409)",
"com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.load(DynamoDBMapper.java:447)",
"com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.load(AbstractDynamoDBMapper.java:85)",
"com.podcast_reviews_service.dynamodb.EpisodeDao.getEpisode(EpisodeDao.java:35)",
"com.podcast_reviews_service.dynamodb.EpisodeDao.saveEpisode(EpisodeDao.java:50)",
"com.podcast_reviews_service.activity.AddEpisodeActivity.handleRequest(AddEpisodeActivity.java:35)",
"java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
"java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
"java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
"java.base/java.lang.reflect.Method.invoke(Unknown Source)"
]
I haven't yet implemented the class that utilizes the GSI. I tried without the secondary index annotation but since my table has them I get the same error.
The error makes me think that I either annotated the Episode class wrong or I'm sending a null value as HASH key for the GSI, which I'm pretty sure I'm not.

You must define the name of your index for the indexhashkey.
#DynamoDBIndexHashKey(attributeName = "podcast",globalSecondaryIndexNames={ "my-index-name"})
public String getPodcast() {return podcast;}

Related

How to write test class for salesforce email template

I'm struggling to write a test class for visualforce email template that I have created as per business requirements but I don't know who to cover "get' methods in the test class.. I spent long hours doing research on google unfortunately I haven't found anything helpful.
I tried many ways to cover 'get' method in test class like below
myClass cls = new myClass;
cls.getMethod();
cls.getProperty = 'test';
but it's giving me the error message "List index out of bounds: 0" because I'm calling another method in getter and that methods takes list of records
Controller Class:
public class JobChangesEmail_ComplianceTeam_Cls {
public string jobId {get; set;}
// public string jUrl{get; }
// public string clientUrl {get; }
// public string endclientUrl {get;}
public static list<job__c> jobs;
public JobChangesEmail_ComplianceTeam_Cls()
{
jobs = [select j.Id,j.name,j.other_location__c,j.account__c,j.account__r.id, j.account__r.name,j.Job_Start_Date__c,j.Job_End_Date__c,j.Job_Status__c,j.account__r.Spreadsheet_SOPs__c,
j.account__r.Facility_SOPs__c,j.End_Client__c,End_Client__r.id,j.End_Client__r.name,j.End_Client__r.Spreadsheet_SOPs__c, j.End_Client__r.Facility_SOPs__c from Job__c j where Id=:jobId];
system.debug('-------------------------------------jobId '+jobId);
}
public list<job__c> getjbs()
{
jobs = [select j.Id,j.name,j.other_location__c,j.account__c, j.account__r.name,j.Job_Start_Date__c,j.Job_End_Date__c,j.Job_Status__c,j.account__r.Spreadsheet_SOPs__c,
j.account__r.Facility_SOPs__c,j.End_Client__c,j.End_Client__r.name,j.End_Client__r.Spreadsheet_SOPs__c, j.End_Client__r.Facility_SOPs__c from Job__c j where Id=:jobId];
system.debug('-------------------------------------jobId '+jobId);
return jobs;
}
Public static string generatejobUrl(list<job__c> jobs)
{
string jurl = System.URL.getSalesforceBaseUrl().toExternalForm() + '/'+jobs[0].Id;
return jurl;
}
Public static string generateclientUrl(list<job__c> jobs)
{
string cUrl = System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+jobs[0].account__r.id;
return cUrl;
}
Public static string generateEndclientUrl(list<job__c> jobs)
{
string endCUrl = System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+jobs[0].end_client__r.id;
return endCUrl;
}
public String getjUrl()
{
string jbUrl;
list<job__c> jobs = [select Id,name from Job__c where Id=:jobId];
jbUrl= System.URL.getSalesforceBaseUrl().toExternalForm() + '/'+jobs[0].Id;
return jbUrl;
}
public string clientUrl
{
get { return generateclientUrl(jobs); }
}
public string endclientUrl
{
get { return generateEndclientUrl(jobs); }
}
}
Test class I have written so far:
#isTest(seeAllData= true)
Public class JobChangesEmail_ComplianceTeam_Cls_test {
#isTest
public static void createJob()
{
string clienturl;
string endClienturl;
string joburl;
list<job__c> jobs = new list<job__c>();
Account a = new account(name='ghghghg',type='Other', Account_Status__c='Active',phone='9090909090');
insert a;
Contact contact = new Contact(FirstName='John',LastName='Adams',email='test#gamil.com',phone='14243443', accountid = a.id);
insert contact;
// Opportunity o = [Select id, Name, CloseDate ,Location__c ,AccountId from opportunity limit 1];
Job__c job = new Job__c();
job.Name = 'NewJob'; // Set to match test record
job.X_KOL__c = false; // Set to match test record
job.DE_Job_Type__c = null; // Set to match test record
job.Job_Name_Subject__c = 'TestJob';
job.Job_Start_Date__c = Date.today();
job.End_Client__c = a.Id;
job.Other_Location__c = 'SOS'; // Set to match test record
job.PM__c = 'Amber Anderson';
job.Booked_By__c = UserInfo.getUserId();
job.Account_Manager_COE__c = UserInfo.getUserId();
job.Account__c = a.Id;
job.Contact__c = contact.Id;
job.Respondent_Type__c = 'Acne';
job.Job_Status__c = 'Tentative';
job.Job_Qualification__c = 'Qualitative';
job.Recruitment_Method__c = 'Client List';
job.On_Site_Recruits__c = 5;
job.Off_Site_Recruits__c = 5;
job.London_Project_Number__c = 'Valyria';
job.Recruiting_Begin_Date__c = Date.today();
jobs.add(job);
if(jobs.size()>0)
{
insert jobs;
}
test.startTest();
clienturl = JobChangesEmail_ComplianceTeam_Cls.generateclientUrl(jobs);
endClienturl = JobChangesEmail_ComplianceTeam_Cls.generateEndclientUrl(jobs);
joburl = JobChangesEmail_ComplianceTeam_Cls.generatejobUrl(jobs);
Test.stopTest();
string cUrl = System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+jobs[0].account__r.id;
string Eurl = System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+jobs[0].end_client__r.id;
string jUrl = System.URL.getSalesforceBaseUrl().toExternalForm() + '/'+jobs[0].Id;
system.assertEquals(clienturl, cUrl);
system.assertEquals(endClienturl, Eurl);
system.assertEquals(joburl, jUrl);
JobChangesEmail_ComplianceTeam_Cls cls = new JobChangesEmail_ComplianceTeam_Cls();
cls.getjbs();
string id = cls.jobId;
id = [select id from job__c limit 1].id;
system.assertNotEquals(id,job.id);
}
}
above test class is not covering get methods or properties

How to use #UsingDataSet in Arquillian test

I have trouble using #UsingDataSet in my project.
Example in manual https://docs.jboss.org/author/display/ARQ/Persistence
doesn`t helps.
I have simple entity:
#Entity(name = "game")
#Table(name = "game_entity", schema = "graph")
#GenericGenerator(name="uuid2", strategy = "uuid2")
public class Game implements Serializable {
private static final long serialVersionUID = -4832711740307931146L;
private UUID id;
private String name;
#Id
#GeneratedValue(generator="uuid2")
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
#NotNull
#Column(name = "name", length = 256, nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object value) {
if (!(value instanceof Game)) {
return false;
}
if (value == this) {
return true;
}
Game obj = (Game) value;
if (!obj.getId().equals(getId())) {
return false;
}
return true;
}
#Override
public int hashCode() {
int result = 29;
result += 29 * (getId() != null ? getId().hashCode() : 0);
result += 29*(getName() != null ? getName().hashCode() : 0);
return result;
}
}
And .yml file
game_entity:
- id : d5c58afd-7c99-41bb-ab0a-6357bfddfe14
name : Call of Duty
My test:
public class MyTest extends Arquillian {
#PersistenceContext(unitName = "spo")
private EntityManager em;
#Test
#UsingDataSet("datasets/gameDataSet.yml")
public void testAttribute() {
System.out.println("Hello world !");
}
#Deployment
public static WebArchive createArchive() {
WebArchive war = ShrinkWrap
.create(WebArchive.class, "myTest.war")
.addAsLibraries(
// blah-blah-blah
)
.addAsResource("my-persistence.xml", "META-INF/persistence.xml")
//.addAsResource("datasets/gameDataSet.yml", "datasets/gameDataSet.yml") // do I need to add this to archive ??
.addAsWebInfResource("META-INF/beans.xml", "beans.xml")
.setWebXML("web.xml")
;
return war;
}
}
When I run this test I getting 2 "strange" exeptions.
Sometimes:
Caused by: org.dbunit.dataset.NoSuchColumnException: game_entity.ID - (Non-uppercase input column: id) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
But there are 2 columns in database! "id" and "name"
Sometimes, even more strange exception:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "info_resource_attributes" does not exist
This is cross-table for another 2 entities, it exist in archive and myPersistence.xml but I dont use them in this test.
I use Wildfly 10 and Postgres 9.5. Without #UsingDataSet everything fine.
But I dont want programmaticaly hardcode data for tests like that:
Entity newEntityForTest = new Entity();
newEntityForTest.setA(...);
newEntityForTest.setB(...);
newEntityForTest.setC(...);
em.persist(newEntityForTest);
// testing ...
em.remove(newEntityForTest);

Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value:

Hi here is Bussinss object class where pwdId and userId are notnull in db
#Entity
#Table(name="CLOUD_SVR_PASSWORDS_HISTORY")
#NamedQuery(name="CloudSvrPasswordsHistory.findAll", query="SELECT c FROM CloudSvrPasswordsHistory c")
public class CloudSvrPasswordsHistory implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="PWD_ID",nullable=false)
private long pwdId;
#Column(name="OLD_PASSWORD")
private String oldPassword;
#Column(name="CURRENT_PASSWORD")
private String currentPassword;
#Column(name="PWD_CHANGE_TYPE")
private String pwdChangeType;
#Column(name="CREATED_DATE")
private Timestamp createdDate;
#ManyToOne
#JoinColumn(name="USER_ID",nullable=false)
private CloudSvrUser user;
public long getPwdId() {
return pwdId;
}
public void setPwdId(long pwdId) {
this.pwdId = pwdId;
}
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getCurrentPassword() {
return currentPassword;
}
public void setCurrentPassword(String currentPassword) {
this.currentPassword = currentPassword;
}
public String getPwdChangeType() {
return pwdChangeType;
}
public void setPwdChangeType(String pwdChangeType) {
this.pwdChangeType = pwdChangeType;
}
public Timestamp getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}
public CloudSvrUser getUser() {
return user;
}
public void setUser(CloudSvrUser user) {
this.user = user;
}
here is my service implementation class only one method I am specifyng
#Transactional
public void changePassword(CloudSvrPasswordsHistory pwdInfo)throws BusinessException
{
//String password=null;
try{
System.out.println("servcimpl----------");
CloudSvrUser dbUser =getUser(pwdInfo);
if(dbUser != null){
List<CloudSvrPasswordsHistory> newPwdList = new ArrayList<CloudSvrPasswordsHistory>();
CloudSvrPasswordsHistory changedPwd = new CloudSvrPasswordsHistory();
changedPwd.setOldPassword(pwdInfo.getOldPassword());
changedPwd.setCurrentPassword(pwdInfo.getCurrentPassword());
newPwdList.add(changedPwd);
dbUser.setPassCode(changedPwd.getCurrentPassword());
//set childs to parent
pwdInfo.setUser(dbUser);
dbUser.setUserPwdList(newPwdList);
//password=
changedPwd(dbUser);
System.out.println("serviceimplend---------");
}
}
catch(DaoException daoexception)
{
throw new BusinessException(daoexception.getMessage());
}
//return password;
}
here is my DAOImpl class
#Repository("passwordDao")
public class PasswordDaoImpl extends BaseDaoImpl implements PasswordDao
{
PasswordDaoImpl()
{}
public void ChangedPwd(CloudSvrUser user)
{
//String password=null;
List<CloudSvrPasswordsHistory> pwdinfo = user.getUserPwdList();
for(CloudSvrPasswordsHistory changedPwd:pwdinfo)
{
//changedPwd.setPwdId((new Long(1)));
changedPwd.setCreatedDate(new Timestamp(System.currentTimeMillis()));
changedPwd.setPwdChangeType("ByUser");
}
try{
super.getHibernateTemplate().update(user);
//this.userDao.updateUser(dbUser);
}
catch(DataAccessException accessException){
throw new DaoException("Internal DB error occured.");
}
//return password ;
}
when giving request getting exception in console
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.omnypay.dao.bo.CloudSvrPasswordsHistory.user
please help me
The error says the user property of CloudSvrPasswordsHistory entity is null, where as hibernate is expecting it to be not-null, this is because you told hibernate that nullable=false for user property using this mapping:
#ManyToOne
#JoinColumn(name="USER_ID",nullable=false)
private CloudSvrUser user;
So to fix the issue you have to set the user property for your CloudSvrPasswordsHistory entity as:
changedPwd.setUser(dbUser);

how can i resolve this "Etat HTTP 500 - java.lang.NullPointerException"?

i'm developping a restful web service that extract data (messages) from my database and return all messages!
every single message is a MsgBean ( with an id, contenu, from, numexp,... )
the web service couldn't return a table so i created a new object that contain a table (msgTable) of MsgBean !
while running my web service on the rest console, i got this error :
Etat HTTP 500 - java.lang.NullPointerException
type Rapport d''exception
message java.lang.NullPointerException
description Le serveur a rencontré une erreur interne qui l''a empêché de satisfaire la requête.
Click to see the rest of error
my MsgBean is :
#XmlRootElement
public class MsgBean implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String frommm;
private String contenu;
private String DateEnvoi;
private String NumExp;
private int idu;
public MsgBean(){};
#XmlElement
public int getIdu() {
return idu;
}
public void setIdu(int idu) {
this.idu = idu;
}
#XmlElement
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement
public String getFrommm() {
return frommm;
}
public void setFrommm(String frommm) {
this.frommm = frommm;
}
#XmlElement
public String getContenu() {
return contenu;
}
public void setContenu(String contenu) {
this.contenu = contenu;
}
#XmlElement
public String getDateEnvoi() {
return DateEnvoi;
}
public void setDateEnvoi(String DateEnvoi) {
this.DateEnvoi = DateEnvoi;
}
#XmlElement
public String getNumExp() {
return NumExp;
}
public void setNumExp(String NameExp) {
this.NumExp = NameExp;
}
}
my msgTabl is :
#XmlRootElement
public class msgTabl implements Serializable {
String test;
MsgBean[] m = new MsgBean[100];
public msgTabl(){};
#XmlElement
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
#XmlElement
public MsgBean getM(int i) {
return m[i];
}
public void setM(int i, MsgBean mb) {
this.m[i].setId(mb.getId());
this.m[i].setIdu(mb.getIdu());
this.m[i].setFrommm(mb.getFrommm());
this.m[i].setNumExp(mb.getNumExp());
this.m[i].setDateEnvoi(mb.getDateEnvoi());
this.m[i].setContenu(mb.getContenu());
}
}
and here is the web service that i did test with :
#GET
#Path("/historiquemethod")
#Produces("application/json")
//#Produces("text/plain")
public msgTabl historique(
#QueryParam("pseudo") String pseudo,
#QueryParam("motDePasse") String motDePasse
) {
msgTabl tab = new msgTabl();
MsgBean ms = new MsgBean();
// set information into our msg to test
ms.setContenu("contenu");
ms.setFrommm("8080");
ms.setNumExp("2584126");
ms.setId(1);
ms.setIdu(2);
ms.setDateEnvoi("date");
// set the message into the first table case
tab.setM(0, ms);
tab.setTest("ok");
return tab;
}
In setM method do this in first line :
this.m[i] = new MsgBean();
Problem is that you have instantiated your array but the objects are null inside that array. So you need to first instantiate the object at required index and then use it.
UPDATE FOR COMMENT
Make a getter method for your m like this getM() and annotate it with XmlElement(Remove the annotation from your current overloaded getM(int i) method). The method getM(int i) cannot be used by JAXB, since jaxb needs simple getter and setter for your properties.

How to set value of list<String> in DynamicJasper

I need to generate dynamic count of columns in me report. So I set to my JasperPrint the massive of Object:
Object[] obj = new Object[selectedUsers.size()];
//fill the massive
JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), new JRBeanArrayDataSource(obj));
My obj is a class:
public class ResultsDTO {
private String login;
private Integer id;
private List<String> list;
private Object[] results;
public Object[] getResults() {
return results;
}
public void setResults(Object[] results) {
this.results = results;
}
public ResultsDTO(){
}
public ResultsDTO(Integer id,String login) {
super();
this.login = login;
this.id = id;
}
public ResultsDTO(String login, Integer id, List<String> list) {
super();
this.login = login;
this.id = id;
this.list = list;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public void addToList(String day_result){
this.list.add(day_result);
}
}
and then I try to create columns:
FastReportBuilder firstReport = new FastReportBuilder();
List<AbstractColumn> column_list = new ArrayList<AbstractColumn>();
AbstractColumn columnId = getColumn("id", Integer.class,"№", 30, headerStyle, detailStyle);
AbstractColumn columnLogin = getColumn("login", String.class,"ФИО", 150, headerStyle, detailStyle);
for (int i = 0; i < header.size(); i++){
AbstractColumn column = getColumn("results", Object.class, header.get(i), 80, headerStyle, detailStyle);
column_list.add(column);
}
Eventually I have an exception:
net.sf.jasperreports.engine.design.JRValidationException: Report
design not valid :
1. Class "java.lang.Object" not supported for text field expression.
Please, help! I don' know how to use jasper and list or array
Jasper Reports does not allow Object as a valid type for its elements. I has to be one of the following:
String
Number (or any subclass of it)
Date
Boolean
You should ask each element in the form for its class and pass proper class to the column builder.