Any reasonable way to sort DynamoDB tables? - java

I am using spring-data-dynamodb 5.1.0 in my Spring Boot 2.5.4 setup. I am trying to get this sample code to work for sorting on SongTitle column on which I have defined a global secondary index.
Here's my entity object.`public class ImprovedMusic {
#Id
private ImprovedMusicId improvedMusicId;
public ImprovedMusic() {}
public ImprovedMusic(ImprovedMusicId improvedMusicId) {
this.improvedMusicId = improvedMusicId;
}
#DynamoDBHashKey(attributeName = "Artist")
public String getArtist() {
return improvedMusicId != null ? improvedMusicId.getArtist() : null;
}
public void setArtist(String artist) {
if (improvedMusicId == null) {
improvedMusicId = new ImprovedMusicId();
}
improvedMusicId.setArtist(artist);
}
#DynamoDBIndexRangeKey(attributeName = "SongTitle", globalSecondaryIndexNames={"GSISongTitle"})
#DynamoDBIndexHashKey(attributeName="SongTitle", globalSecondaryIndexNames = "GSISongTitle")
public String getSongTitle() {
return improvedMusicId != null ? improvedMusicId.getSongTitle() : null;
}
public void setSongTitle(String songTitle) {
if (improvedMusicId == null) {
improvedMusicId = new ImprovedMusicId();
}
improvedMusicId.setSongTitle(songTitle);
}
}
`
I invoke this code in my test
`Sort sortBy = Sort.by("SongTitle").descending;
Pageable page = PageRequest.of(1,5,sortBy);
Page aPage = myRepositor.findAll(page);`
Please note, I am not trying to search by SongTitle, I want this list to be sorted by the songtitle. The above test throws the following exception. Anything I am doing wrong here?
The number of conditions on the keys is invalid (Service:
AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException;
Request ID: c0634958-d465-4560-8dce-3e51519b4ed6)
com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The
number of conditions on the keys is invalid (Service:
AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException;
Request ID: c0634958-d465-4560-8dce-3e51519b4ed6) at
com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1799)
at
com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1

Related

HAPI FHIR #Create Operation not returning MethodOutcome Response

I was basing my program off of the samples on hapishir's website and the operation works in that I receive the JSON body and I'm updating the database. The issue I have though is that there is no response being returned. I build the MethodOutcome object, and "return" it, but nothing appears in postman. I've written #read and #Search operations also and those both return the resource in the response on Postmat, but this #Create doesn't return any response.
ObservationResourceProvider.java
public class ObservationResourceProvider implements IResourceProvider {
public ObservationResourceProvider() { }
#Override
public Class<? extends IBaseResource> getResourceType() {
return Observation.class;
}
#Create()
public MethodOutcome createObservation(#ResourceParam Observation observation){
OpenERMDatabase db = new OpenERMDatabase();
String newObservationId = db.addNewObservation(observation);
//return the new Id if success else return an error message
MethodOutcome retVal = new MethodOutcome();
if (newObservationId != null) {
retVal.setId(new IdType("Observation", newObservationId, "1.0"));
retVal.setCreated(true);
}else {
OperationOutcome outcome = new OperationOutcome();
outcome.addIssue().setDiagnostics("An Error Occurred");
retVal.setOperationOutcome(outcome);
retVal.setCreated(false);
}
return retVal;
}
}
SimpleRestfulServer.java
#WebServlet("/*")
public class SimpleRestfulServer extends RestfulServer{
//Initialize
#Override
protected void initialize()throws ServletException{
//create a context for the appropriate version
setFhirContext(FhirContext.forDstu3());
//Register Resource Providers
registerProvider(new PatientResourceProvider());
registerProvider(new ObservationResourceProvider());
}
}
I've built an environment and debugged the server side code.
I'm sure you will get some hint from this. There are three modes defined in PreferReturnEnum, when you specify an extra header in the HEADERS with key as "Prefer" and value as " return=OperationOutcome", the value defined in operationOutcome will be retured.

The POST request persisted in the MySQL but returns null

I wrote some Java wallet generation code and I use it for generating a crypto-currency wallet. The code is provided,
public synchronized WalletInfo generateAddress(GenerateWallet generateWallet) {
final WalletInfo walletInfo = new WalletInfo();
String walletName = generateWallet.getWalletName();
String currencyName = generateWallet.getCurrencyName();
WalletInfo walletInfoDb = iWalletInfoDao.getWalletInfoWithWalletNameAndCurrency(walletName, currencyName);
if (walletInfoDb == null && genWalletMap.get(walletName) == null) {
String currency = currencyName.toUpperCase();
if (currency.equals("BITCOIN")) {
final WalletManager walletManager = WalletManager.setupWallet(walletName);
walletManager.addWalletSetupCompletedListener((wallet) -> {
Address address = wallet.currentReceiveAddress();
WalletInfo newWallet = createWalletInfo(walletName, currencyName, address.toString());
// set the properties of the walletInfo
walletInfo.setId(newWallet.getId());
walletInfo.setName(newWallet.getName());
walletInfo.setAddress(newWallet.getAddress());
walletInfo.setCurrency(newWallet.getCurrency());
walletMangersMap.put(newWallet.getId(), walletManager);
genWalletMap.remove(walletName);
});
genWalletMap.put(walletName, walletManager);
return walletInfo;
} else if (currency.equals("ETHEREUM")) {
return walletInfo;
} else {
return walletInfo;
}
}
return walletInfo;
}
When I do a POST request using the cURL,
curl -H "Content-Type: application/json" -X POST -d '{"walletName": "Florence8","currencyName":"Bitcoin"}' http://localhost:8080/rest/wallet/generateAddress
I get null is the return,
{
"id" : null,
"name" : null,
"address" : null,
"currency" : null
}
While the entity is generated and still persisted in the MySQL. I keep debugging and this is wired. The debugging doesn't follow top-to-bottom sequence of the code. The sequence of the debugging is like,
The point that I would like to make is if the code comes to this line
walletManager.addWalletSetupCompletedListener((wallet), then it should execute the operations inside.
Any suggestion how do I get the entity back after rightfully persisted in the database? I can provide more info if required
Update
As suggested in the answer, I use a CountDownLatch and solve the problem
public synchronized WalletInfo generateAddress(GenerateWallet generateWallet) {
CountDownLatch finshedSetup = new CountDownLatch(1);
// some code
}
The output in the terminal,
It looks like you're running into a race condition. You're setting up a callback to fill in the walletInfo, but potentially returning walletInfo before the callback has executed.
Some type of promise or latch to wait on before returning could help. For example:
public synchronized WalletInfo generateAddress(GenerateWallet generateWallet) {
final WalletInfo walletInfo = new WalletInfo();
String walletName = generateWallet.getWalletName();
String currencyName = generateWallet.getCurrencyName();
WalletInfo walletInfoDb = iWalletInfoDao.getWalletInfoWithWalletNameAndCurrency(walletName, currencyName);
if (walletInfoDb == null && genWalletMap.get(walletName) == null) {
String currency = currencyName.toUpperCase();
if (currency.equals("BITCOIN")) {
final WalletManager walletManager = WalletManager.setupWallet(walletName);
CountDownLatch finishedSetup = new CountDownLatch(1);
walletManager.addWalletSetupCompletedListener((wallet) -> {
Address address = wallet.currentReceiveAddress();
WalletInfo newWallet = createWalletInfo(walletName, currencyName, address.toString());
// set the properties of the walletInfo
walletInfo.setId(newWallet.getId());
walletInfo.setName(newWallet.getName());
walletInfo.setAddress(newWallet.getAddress());
walletInfo.setCurrency(newWallet.getCurrency());
walletMangersMap.put(newWallet.getId(), walletManager);
genWalletMap.remove(walletName);
finshedSetup.countDown();
});
genWalletMap.put(walletName, walletManager);
finishedSetup.await();
return walletInfo;
} else if (currency.equals("ETHEREUM")) {
return walletInfo;
} else {
return walletInfo;
}
}
return walletInfo;
}

How to get Workflow event type and Processstep name or Arguments in to java service in AEM?

I created a workflow for whenever I upload or remove asset from /content/dam/MyAsset folder I am able to Triggering JavaServices. I create two launcher with Created Event Type and Removed Event Type.
I need to get That event Type and Process step name or arguments in to Services
inside Triggering execute function
Here is My Code:
public void execute(WorkItem arg0, WorkflowSession arg1, MetaDataMap arg2)
throws WorkflowException
{
log.info("Workflow created ::::: ");
}
Is there any way to get Launcher event type and process arguments]to Services ?
You can not get launcher event type as that information is not passed down to the workflow. What you could do is check the payload to identify if the node exists or not. The workflow called on removal will have path to the node that is removed and if you try to resolve that path it will give you exception (yeah, bad approach but thats the only possibility).
For the process step arguments passed, all that information is available in meta data. Look into arg0.getWorkflowData().getMetaDataMap().get("MyIDkey",<Type>); where arg0 is your WorkItem instance.
Why don't you use a org.osgi.service.event.EventHandler instead? You will have all the information you need. Here is a small code snippet that waits for an event and adds the relevant data into a map that is then passed to the JobManager to generate a new Job that is executed by a matching JobConsumer:
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.consumer.JobConsumer;
// and more imports...
#Service
#Component(immediate = true, policy = ConfigurationPolicy.OPTIONAL, description = "Listen to page modification events.")
#Properties(value = { #Property(name = "event.topics", value = { PageEvent.EVENT_TOPIC, DamEvent.EVENT_TOPIC}, propertyPrivate = true),
#Property(name = JobConsumer.PROPERTY_TOPICS, value = ModificationEventHandler.JOB_TOPICS, propertyPrivate = true) })
public class ModificationEventHandler implements EventHandler, JobConsumer {
/**
* Modification Job Topics.
*/
public static final String JOB_TOPICS = "de/rockware/aem/modification";
#Reference
private JobManager jobManager;
#Override
public void handleEvent(Event event) {
logger.trace("Checking event.");
PageEvent pageEvent = PageEvent.fromEvent(event);
DamEvent damEvent = DamEvent.fromEvent(event);
Map<String, Object> properties = new HashMap<>();
if (damEvent != null) {
// DamEvent is not serializable, so we cannot add the complete event to the map.
logger.trace("Event on {} is a dam event ({}).", damEvent.getAssetPath(), damEvent.getType().name());
properties.put(DAM_EVENT_ASSET_PATH, damEvent.getAssetPath());
}
if (pageEvent != null) {
logger.trace("Event is a page event.");
properties.put(PAGE_EVENT, pageEvent);
}
logger.trace("Adding new job.");
jobManager.addJob(JOB_TOPICS, properties);
}
#Override
public JobResult process(Job job) {
if (job.getProperty(PAGE_EVENT) != null) {
PageEvent pageEvent = (PageEvent) job.getProperty(PAGE_EVENT);
if(pageEvent.isLocal()) {
Iterator<PageModification> modificationsIterator;
modificationsIterator = pageEvent.getModifications();
while (modificationsIterator.hasNext()) {
PageModification modification = modificationsIterator.next();
logger.info("Handling modification {} on path {}.", modification.getType(), modification.getPath());
if(isRelevantModification(modification.getType())) {
logger.info(modification.getPath());
}
}
} else {
logger.trace("Page event is not local.");
}
} else if (job.getProperty(DAM_EVENT_ASSET_PATH) != null) {
String assetPath = (String) job.getProperty(DAM_EVENT_ASSET_PATH);
logger.trace(assetPath);
backupService.trackModification(assetPath);
} else {
logger.trace("Invalid event type. Cannot help.");
}
return JobResult.OK;
}
}

AWS S3 - com.amazonaws.AmazonServiceException: Request ARN is invalid

I'm trying to make my android app download images from AWS S3. However, the following exception keeps coming up:
com.amazonaws.AmazonServiceException: Request ARN is invalid (Service: AWSSecurityTokenService; Status Code: 400; Error Code: ValidationError; Request ID: 3481bd5f-1db2-11e5-8442-cb6f713243b6)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:710)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:385)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:196)
at com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient.invoke(AWSSecurityTokenServiceClient.java:875)
at com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient.assumeRoleWithWebIdentity(AWSSecurityTokenServiceClient.java:496)
at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithSts(CognitoCredentialsProvider.java:671)
at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:555)
at com.amazonaws.auth.CognitoCredentialsProvider.refresh(CognitoCredentialsProvider.java:503)
at com.application.app.utils.helper.S3Utils.getCredProvider(S3Utils.java:35)
at com.application.app.utils.helper.S3Utils.getS3Client(S3Utils.java:45)
at com.application.app.integration.volley.CustomImageRequest.parseNetworkError(CustomImageRequest.java:73)
at com.android.volley.NetworkDispatcher.parseAndDeliverNetworkError(NetworkDispatcher.java:144)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:135)
I have a bucket and an identity pool. Also, created required roles.
My Cognito_APPUnauth_Role has the following INLINE POLICY:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1435504517000",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::mybucket/*"
]
}
]
}
I have a java class named S3Utils that has some helper methods.
public class S3Utils {
private static AmazonS3Client sS3Client;
private static CognitoCachingCredentialsProvider sCredProvider;
public static CognitoCachingCredentialsProvider getCredProvider(Context context){
if (sCredProvider == null) {
sCredProvider = new CognitoCachingCredentialsProvider(
context,
Definitions.AWS_ACCOUNT_ID,
Definitions.COGNITO_POOL_ID,
Definitions.COGNITO_ROLE_UNAUTH,
null,
Regions.US_EAST_1
);
}
sCredProvider.refresh();
return sCredProvider;
}
public static String getPrefix(Context context) {
return getCredProvider(context).getIdentityId() + "/";
}
public static AmazonS3Client getS3Client(Context context) {
if (sS3Client == null) {
sS3Client = new AmazonS3Client(getCredProvider(context));
}
return sS3Client;
}
public static String getFileName(String path) {
return path.substring(path.lastIndexOf("/") + 1);
}
public static boolean doesBucketExist() {
return sS3Client.doesBucketExist(Definitions.BUCKET_NAME.toLowerCase(Locale.US));
}
public static void createBucket() {
sS3Client.createBucket(Definitions.BUCKET_NAME.toLowerCase(Locale.US));
}
public static void deleteBucket() {
String name = Definitions.BUCKET_NAME.toLowerCase(Locale.US);
List<S3ObjectSummary> objData = sS3Client.listObjects(name).getObjectSummaries();
if (objData.size() > 0) {
DeleteObjectsRequest emptyBucket = new DeleteObjectsRequest(name);
List<DeleteObjectsRequest.KeyVersion> keyList = new ArrayList<DeleteObjectsRequest.KeyVersion>();
for (S3ObjectSummary summary : objData) {
keyList.add(new DeleteObjectsRequest.KeyVersion(summary.getKey()));
}
emptyBucket.withKeys(keyList);
sS3Client.deleteObjects(emptyBucket);
}
sS3Client.deleteBucket(name);
}
}
Part of the method where the exception occurs, in CustomImageRequest.java:
s3Client = S3Utils.getS3Client(context);
ObjectListing objects = s3Client.listObjects(new ListObjectsRequest().withBucketName(Definitions.BUCKET_NAME).withPrefix(this.urlToRetrieve));
List<S3ObjectSummary> objectSummaries = objects.getObjectSummaries();
//This isn't just an id, it is a full picture name in S3 bucket.
for (S3ObjectSummary summary : objectSummaries)
{
String key = summary.getKey();
if (!key.equals(this.urlToRetrieve)) continue;
S3ObjectInputStream content = s3Client.getObject(Definitions.BUCKET_NAME, key).getObjectContent();
try {
this.s3Image = IOUtils.toByteArray(content);
} catch (IOException e) {
}
return new Object();
}
What am I doing wrong that causes this exception to be thrown every time. Thanks in advance.
I'm guessing there might be an error in the role ARN you specified. A role ARN should look something like
arn:aws:cognito-identity:us-east-1:ACCOUNTNUMBER:identitypool/us-east-1:UUID
If it is misspelled, or part is left off you may get the error. You may also want to consider user the new CognitoCachingCredentialsProvider constructor.
sCredProvider = new CognitoCachingCredentialsProvider(
context,
Definitions.COGNITO_POOL_ID,
Regions.US_EAST_1
);
However note that you will have to make sure that you have specified your role ARN in the Cognito console, but it should help prevent this issue in the future.
Edited for clarity, formatting, and added that you need to modify your ARN in the console if using new constructor.

Alternative to NamedParameterJDBC template row mapper in Hibernate

I have to convert the following NamedSqlParameterSource in Hibernate:-
final List<MenuActionMapping> menusList;
MapSqlParameterSource sqlParams = new MapSqlParameterSource();
menusList = namedParameterJdbcTemplate.query("call sp_proc()",sqlParams ,new RowMapper<MenuActionMapping>() {
#Override
public MenuActionMapping mapRow(ResultSet resultset, int i)
throws SQLException {
MenuActionMapping menuActionMapping=new MenuActionMapping();
menuActionMapping.setMenuKey(resultset.getString("KMM_MENU_KEY"));
menuActionMapping.setDisplayName(resultset.getString("KMM_DISPLAY_NAME"));
menuActionMapping.setMenuActionFlag(resultset.getInt("KMM_ACTION_FLAG"));
menuActionMapping.setMenuActive(resultset.getInt("KMM_ACTIVE"));
menuActionMapping.setMenuLevel(resultset.getInt("str_len"));
String str=resultset.getString("menu_actions");
String [] actions=str.split(",");
if(resultset.getInt("KRMM_ACTIVE")==1)
{
menuActionMapping.setActive(true);
}
else
{
menuActionMapping.setActive(false);
}
for(String strAct:actions)
{
if(strAct.equals("ADD"))
{
menuActionMapping.setAddCheckBox(true);
menuActionMapping.setAddCheckBoxDisabled("true");
}
if(strAct.equals("VIEW"))
{
menuActionMapping.setViewCheckBox(true);
menuActionMapping.setViewCheckBoxDisabled("true");
}
if(strAct.equals("DELETE"))
{
menuActionMapping.setDeleteCheckBox(true);
menuActionMapping.setDeleteCheckBoxDisabled("true");
}
if(strAct.equals("EDIT"))
{
menuActionMapping.setEditCheckBox(true);
menuActionMapping.setEditCheckBoxDisabled("true");
}
if(strAct.equals("DOWNLOAD"))
{
menuActionMapping.setDownloadCheckBox(true);
menuActionMapping.setDownloadCheckBoxDisabled("true");
}
}
return menuActionMapping;
}
});
System.out.println(menusList);
return menusList;
I dont have idea about how namedJdbcTemplate and Map Row Works so i am getting a Problem..
I also wrote alternate code in hibernate but it doesnt work:-
final List<MenuActionMapping> menusList;
Query query= getSession().createSQLQuery("call kyc.sp_proc()");
menusList=query.list();
System.out.println(menusList);
return menusList;
I think I am not setting MenuAction Mapping Object so how to achive the purpose?
Also I want to Manipulate the columns before setting it into the object how can i do it in hibernate....
The main code that is troubling me is this:-
String str=resultset.getString("menu_actions");
String [] actions=str.split(",");
if(resultset.getInt("KRMM_ACTIVE")==1)
{
menuActionMapping.setActive(true);
}
else
{
menuActionMapping.setActive(false);
}
for(String strAct:actions)
{
if(strAct.equals("ADD"))
{
menuActionMapping.setAddCheckBox(true);
menuActionMapping.setAddCheckBoxDisabled("true");
}
if(strAct.equals("VIEW"))
{
menuActionMapping.setViewCheckBox(true);
menuActionMapping.setViewCheckBoxDisabled("true");
}
if(strAct.equals("DELETE"))
{
menuActionMapping.setDeleteCheckBox(true);
menuActionMapping.setDeleteCheckBoxDisabled("true");
}
if(strAct.equals("EDIT"))
{
menuActionMapping.setEditCheckBox(true);
menuActionMapping.setEditCheckBoxDisabled("true");
}
if(strAct.equals("DOWNLOAD"))
{
menuActionMapping.setDownloadCheckBox(true);
menuActionMapping.setDownloadCheckBoxDisabled("true");
}
How to set mutiple attribute based in 1 column in hibernate...
namedJdbcTemplate helps you to reduce the boilerplate code like getting,closing connection etc while Row mapper helps you to iterate over returned result set and map it to desired Java class.
Check this http://www.mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate/
Thanks To #Pratik on How to map columns in hibernate with class attributes?
I got the answer to my question i can achieve the same as row mappper of jdbc template in hibernate using BasicTransformerAdapter in hibernate. My code is as follows:-
final List<MenuActionMapping> menusList;
menusList = getSession().createSQLQuery("CALL kyc.sp_proc()").setResultTransformer(new BasicTransformerAdapter() {
private static final long serialVersionUID = 1L;
#Override
public Object transformTuple(Object[] tuple, String[] aliases)
{
MenuActionMapping menuActionMapping=new MenuActionMapping();
menuActionMapping.setMenuId((Integer)tuple[0]);
menuActionMapping.setMenuKey((String)tuple[1]);
menuActionMapping.setDisplayName((String)tuple[3]);
menuActionMapping.setMenuActionFlag((Integer)tuple[5]);
final Boolean b=(Boolean)tuple[6];
menuActionMapping.setMenuActive(b? 1 : 0);
final BigInteger big=(BigInteger) tuple[9];
menuActionMapping.setMenuLevel(big.intValue());
String str=(String)tuple[10];
String [] actions=str.split(",");
if(b==true)
{
menuActionMapping.setActive(true);
}
else
{
menuActionMapping.setActive(false);
}
for(String strAct:actions)
{
if(strAct.equals("ADD"))
{
menuActionMapping.setAddCheckBox(true);
menuActionMapping.setAddCheckBoxDisabled("true");
}
if(strAct.equals("VIEW"))
{
menuActionMapping.setViewCheckBox(true);
menuActionMapping.setViewCheckBoxDisabled("true");
}
if(strAct.equals("DELETE"))
{
menuActionMapping.setDeleteCheckBox(true);
menuActionMapping.setDeleteCheckBoxDisabled("true");
}
if(strAct.equals("EDIT"))
{
menuActionMapping.setEditCheckBox(true);
menuActionMapping.setEditCheckBoxDisabled("true");
}
if(strAct.equals("DOWNLOAD"))
{
menuActionMapping.setDownloadCheckBox(true);
menuActionMapping.setDownloadCheckBoxDisabled("true");
}
}
return menuActionMapping;
}
}).list();

Categories

Resources