Grails application showing wrong date - sql-server

I've developed a grails application with grails-2.4.5, SQL Server 2008 R2 database and facing a strange problem. In one of my domain class there's a field of Date datatype. When i am submitting data from the respective form it saves it correctly to the database but in the show view the date shows two days ago the saved date. As for example I input 08 June 1992, it saves to database as "1992-06-08 00:00:00.0000000", but in the show view it becomes "06/06/1992"
I used the g:formatDate tag in the show page. ( <g:formatDate format="dd/MM/yyyy"
date="${aaaOrganizationInstance?.dateOfEstablish}"/> )
Controllers save action:
#Transactional
def save(AaaOrganization aaaOrganizationInstance) {
if (aaaOrganizationInstance == null) {
notFound()
return
}
if (aaaOrganizationInstance.hasErrors()) {
respond aaaOrganizationInstance.errors, view:'create'
return
}
aaaOrganizationInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'aaaOrganization.label', default: 'AaaOrganization'), aaaOrganizationInstance.id])
redirect aaaOrganizationInstance
}
'*' { respond aaaOrganizationInstance, [status: CREATED] }
}
}

There's a known issue with the SQL Server JDBC driver that causes your symptom. Here's a related question.
The solution
To fix the issue you can install the updated JDBC driver here.

Related

ASP.NET MVC 5 'DateTime' cannot be saved on sql server 'datetime' format on Release (published) mode but works on Debug mode

So I have an ASP.NET MV5 app, I'm using Entity Framework 6 and a SQL Server database. I also use this: datepicker
I have bootstrap-datepicker input with this format: 'dd.mm.yyyy'. With jQuery I get this field's value, which is exactly like this "29.01.2022" and I send it to an ASP.NET MVC action method which expects a DateTime parameter.
On my action that parameter is converted automatically to DateTime format but keeps the correct date.
Datepicker configuration:
$(".input-daterange") {
language: 'ro',
format: 'dd.mm.yyyy',// this gives 29.01.2022
//format: 'dd.MM.yyyy',// this gives 29.Jan.2022
autoclose: true,
calendarWeeks: true,
clearbtn: true,
disableTouchKeyboard: true
}
I'm using Entity Framework 6 for database access, so my code looks something like this:
public Action SaveField(int rowId, DateTime fieldDateValue)
{
var itemToUpdate = _context.TableName.Single(i => i.id = rowId); // this is not null
itemToUpdate.StartDate = fieldDateValue;
try
{
_context.SaveChanges()
}
catch
{ ... }
}
This code works well in debug mode but when I publish the app all gets crazy, I get an error
String was not recognized as a valid DateTime
What I've tried so far (because of datepicker format: dd.mm.yyyy):
itemToUpdate.StartDate = fieldDateValue
itemToUpdate.StartDate = Convert.ToDateTime(fieldDateValue.ToString("yyyy-MM-dd HH:mm:ss")) --> this worked for a few times but the saved date in the database was from 29.01.2022 to 2022-29-01 so something like yyyy-MM-dd, but gives be error too
itemToUpdate.StartDate = DateTime.ParseExact(fieldDateValue.ToString(), "dd.mm.yyyy", CultureInfo.InvariantCulture);
itemToUpdate.StartDate = DateTime.ParseExact(fieldDateValue.ToShortDateString(), "dd.mm.yyyy", CultureInfo.InvariantCulture);
I simply cannot understand what am I doing wrong giving the fact that the published version of the app I'm running on a remote server (which might explain issues) but also on the same machine (IIS wwroot).
Can someone tell how to correctly manage the date format so there will be no more problems and differences between debug and release versions?
So, finally, what actually worked for published version of my app was this:
date format in SQL Server database (datetime not working)
made my filed in ViewModel as 'string' instead of DateTime
DateTime.ParseExact(fieldDateValue, "dd.MM.yyyy", CultureInfo.InvariantCulture)
Build -> Clean project then Publish it (just for safety, when you do a lot of publishing) -> this also solves publish failures with Visual Studio 2015 (first time fail than second get's published)
Also for failed publishing, last solution is to delete obj folder from project
For some reason DateTime.ParseExact(fieldDateValue.ToShortDateString(), "dd.MM.yyyy", CultureInfo.InvariantCulture) didn't work in release mode

SalesForce query returns results in Query Editor, but returns null from APEX code in Lightning component

I'm completely new to SalesForce and have inherited a report that's not working. Please excuse any incorrect terminology, since I'm learning about all this as I go. The report has three prompts: states, years, and members. All dropdowns are supposed to populate with data returned from functions in an APEX class. State, which populates from a picklist, and years, which is populated with a loop, work fine. Members, which populates from a SQL query, returns nothing. If I run the report without any prompts selected (which should return an unfiltered list of results from a SQL query), it also returns nothing. Both of the SQL queries return data when I execute them directly in the query editor in the developer console, but they return nothing when called from the APEX functions.
Here's the initialization code from the Lightning controller:
doInit: function (component, event, helper) {
var action = component.get('c.getTrcAccounts');
action.setCallback(this, function (response) {
var state = response.getState();
if (state === 'SUCCESS' && component.isValid()) {
component.set('v.trcAccList', response.getReturnValue());
}
helper.getLocationState(component, event);
helper.getYear(component, event);
});
$A.enqueueAction(action);
},
Here are the two helper functions referenced in that code:
getLocationState: function (component, event) {
var action = component.get('c.getLocationState');
action.setCallback(this, function (response) {
var state = response.getState();
if (state === 'SUCCESS') {
component.set('v.LocationStateList', response.getReturnValue());
}
});
$A.enqueueAction(action);
},
getYear: function (component, event) {
var action = component.get('c.yearsOptions');
action.setCallback(this, function (response) {
var state = response.getState();
if (state === 'SUCCESS') {
component.set('v.LocationYearList', response.getReturnValue());
}
});
$A.enqueueAction(action);
}
Here is the code from the APEX class that returns the data for those three prompts:
Global class DataTableLocations {
#AuraEnabled
Global static List<TRC_Account__c> getTrcAccounts(){
set<string> trcAccountSet = new set<string>();
List<TRC_Account__c> traccList = new List<TRC_Account__c>();
for(TRC_Account__c trcacc : [SELECT Id, Name from TRC_Account__c WHERE TRC_Member__c = True order by Name limit 50000]){
if(!trcAccountSet.contains(trcacc.Name)){
trcAccountSet.add(trcacc.Name);
traccList.add(trcacc);
}
}
if(traccList.size()>0){
return traccList;
}
else{
return null;
}
}
#AuraEnabled
Global static List<string> getLocationState(){
List<string> options = new List<string>();
//options.add(new SelectOption('SelectAll', 'Select All'));
for( Schema.PicklistEntry f : Location__c.Physical_Address_State__c.getDescribe().getPicklistValues()) {
options.add(f.getValue());
}
return options;
}
#AuraEnabled
Global static List<string> yearsOptions() {
List<string> options = new List<string>();
date OldDate= date.today().addYears(-18);
integer oldyear=OldDate.year();
for( integer i=0; i<19 ;i++) {
options.add(string.valueOf(oldyear));
oldyear++;
}
return options;
}
}
If I run SELECT Id, Name from TRC_Account__c WHERE TRC_Member__c = True order by Name limit 50000 directly in the query editor window in the developer console, I get 7 results. However, if I output the response.getReturnValue() for getTrcAccounts in the doInit function, it's null.
Any help is greatly appreciated, as we're in a bit of a time crunch in conjunction with a site redesign. I'm told these reports were working at one point, but no one knows when they stopped working, and we inherited this code from a different company that did the original development. Thank you!
UPDATE:
In case it helps, this is the code in the lightning app that I think is used on the public page:
<aura:application extends="ltng:outApp" access="GLOBAL" implements="ltng:allowGuestAccess">
<aura:dependency resource="c:SearchBinReceiptsByYear"/>
</aura:application>
Edit
Right, it's a public page, it's called "Salesforce Sites". It's exposed to whole world without having to log in. These have special security in place because most of the time you don't want to expose data like that. At best you'd display contact us form, maybe some documents to download, product catalog... It's all very locked down, default is to ban everything and then admin decides what's allowed. It's bit unusual to have a Visualforce page + Aura component but ok, it happens.
You (and any other internal user) can see the results if you'd access this page from within salesforce. Something like https://mydomain.my.salesforce.com/apex/SearchBinReceiptsByYear and for you the page will work fine, "just" not outside of salesforce.
When exposed like that on the web - there's no logged in user. There's special "[Site Name] Guest User", you can see them if you search "Sites" in Setup. It has a special profile, also with [Site Name] in it. And nasty thing is - it doesn't show on the list of Users or Profiles.
Your code broke when Salesforce (auto)activated a critical update. Probably this one: https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_networks_secure_perms_guests.htm There are some good resources on the net if you Google "Secure Object Permissions for Guest Users", for example https://katiekodes.com/salesforce-spring-20-guest-user/
Ask your system administrator colleague or read up a bit about sharing rules.
You'll have to go to Setup -> Sharing Rules. There's a checkbox that caused your stuff to break and you can't untick it.
Scroll down to your TRC Account object and hit "New". You'll need to create something like this, but with your criteria (TRC Member equals true)
Save, wait a bit (it might take a while to recalculate the sharing, you'll get an email) and try the page.
If it still doesn't work you'll have to check the Guest user's profile, it might need permissions to Read TRC Accounts and their Name field.
If it's Salesforce Sites - try this to find it: https://help.salesforce.com/articleView?id=000334554&type=1&mode=1
If it's a Customer Portal, Community, Digital Experience (they renamed the product few times) - try with https://help.salesforce.com/articleView?id=sf.rss_config_guest_user_profile.htm&type=5
Original answer
It looks like it's running OK because accounts (members?) are fetched first and in that fetch's callback (what to do when data comes back from server) you have helper.getLocationState, helper.getYear. And you wrote that these populate OK. It's not the best performance code but it should get the job done.
In no specific order...
Does the whole thing work OK for sysadmins? Or is it broken for everybody? If it works for sysadmins it might be something to do with sharing, your sysadmin should know (Setup -> Sharing settings is where you control who can see what. Maybe "mortals" are not allowed to see any data? Typically sysadmins bypass it. As a quick & dirty test you can modify the class definition to global without sharing class DataTableLocations but it's a really ugly hack.
What happens if you open DeveloperConsole (upper right corner) while running this component, do you see any errors in the logs? What happens if in the console you go Debug -> Open ExecuteAnonymous and run this piece of code:
System.debug(DataTableLocations.getTrcAccounts());
Does it return something? Throw error?
You can go to Setup -> Debug Mode, tick the checkbox next to your user and save. This slows the system down a bit but lets you debug the javascript better. You can then sprinkle some debugger; or console.log statements in the source code and view what happens in your browser's console (Ctrl+Shift+J in Chrome, Ctrl+Shift+I in firefox). For example
action.setCallback(this, function (response) {
var state = response.getState();
debugger;
console.log(state);
console.log(component.isValid());
console.table(response.getReturnValue());
if (state === 'SUCCESS' && component.isValid()) {
component.set('v.trcAccList', response.getReturnValue());
}
console.log(component.get('v.trcAccList'));
debugger;
helper.getLocationState(component, event);
helper.getYear(component, event);
});
How's the trcAccList variable actually used in the "cmp" file, in the HTML-like file? Maybe it's being set all right and contains 7 records but it's not displayed right?

React Native - How to connect to AWS DynamoDB table

I am following this aws tutorial to create my first React Native app which connects to AWS:
aws tutorial
Everything installs fine and my app runs happily with the following imports:
**import Amplify from 'aws-amplify';
import aws_exports from './aws-exports';
Amplify.configure(aws_exports);**
I would now like to connect the app to an existing DynamoDB table called 'Movement' but the tutorial only shows how to create a new table with the NoSQL wizard using: awsmobile database enable --prompt
Could you point me to a (simple) resource that shows me how to connect to an existing DynamoDB table and perform CRUD operations?
These are the steps I have followed:
I have a DynamoDB table called: movement
It has 3 items : hub_id, on_time, message
Hub_id is the primary partition key
on_time is the primary sort key
The table holds sensor data (movement, temperature that sort of thing) in the message item.
I created the app using :
create-react-native-app dbapp
I have then run:
awsmobile configure
aws mobile init
Installed amplify:
npm install aws-amplify --save
I created the project in mobile hub.
I then linked the app to the hub using:
awsmobile init 15c482e2-2c3c-11e8-8692-fblahblahblah3
CLI responded : Successfully linked AWS Mobile Hub project: dbapp-datetime!
So all looks good so far (I hope!)
I then altered app.js to look like this: pastebin
npm start runs just fine with no errors that I can see.
The problem that I currently have is that I don't have a clue about how to query my table and populate variables so that I can use them in the view.
Following the resources suggested (thanks SteveB). I connected to the DynamoDB table, queried it and used the data in my app.
In case you are also stuck, here is an edited version of my code. Apologies to everyone that gets to edit this - I know it is awful. Does work though :)
// Use db to query the dynamoDB table - setup query parameters first //
var params = {
TableName : "myproject-mobilehub-123456789-Sensors",
ProjectionExpression:"hub_id, details.on_time, details.sensor_name,
details.temperature, details.battery",
KeyConditionExpression: "hub_id = :hid AND begins_with(on_time, :d)",
ExpressionAttributeValues: {
":hid":"testdevice01",
":d": today,
},
Limit: 1,
ScanIndexForward: false
};
//Execute db query using params
async getQuery() {
db.query(params, function(err, data) {
if (err) { console.log("Query failed.");
} else {
console.log("Query succeeded.");
};
data.Items.forEach(function(details) {
//display variables
console.log(details.hub_id,details.details.sensor_name,details.details.on_time,
details.details.temperature, details.details.battery,);
//Populate variables
hubid = details.hub_id;
currroom = details.details.sensor_name;
roomtime = details.details.on_time;
roomtemp = details.details.temperature;
roombattery = details.details.battery + "%";
});
}});
//Finally populate text with variables
this.setState({
displayText1: currroom,
displayText2: roombattery,
displayText3: roomtime,
displayText4: roomtemp
});

How do I use another database other than default in play-framework?

Up until I was using only one database in my application. So for any sql query, I was just using the default database. Below is given the info about the database.
db.default.driver=org.postgresql.Driver
db.default.url="postgres://user:password#localhost:5439/database_name"
These info are saved in the appliction.conf file. In the code below DB is the default database.
DB.withConnection {
conn =>
{
val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)
try {
statement.execute(sql)
}
catch {
case e: Exception => Logger.debug("There is some error with the database")
}
}
}
But I need to use another database. Below is given the info about the database.
db.um.driver=com.mysql.jdbc.Driver
db.um.url="mysql://user:password#localhost:3306/database_name"
These info are also saved in the application.conf file. Now how do I access that database and run an sql command.
The data source called default, as the name suggests, is used as a default value for all connections. You can see that the withConnection() method takes a parameter with a data source name but if nothing is passed, "default" is used instead.
To use your additional data source you have to specify it as a parameter of the withConnection() method.
DB.withConnection("um") { conn =>
// implement your action
}
In case someone is like myself, is looking to use multiple data resources in Play 2.6: This is not the answer.
We need to define the name of the database when we inject the instance of the Database, using #NamedDatabase:
class Customer #Inject()(#NamedDatabase("customer") db: Database){ ??? }

Can I customize my AngularJS application to display local times?

I am using an ASP.NET MVC / ASP.NET Web API back-end for my application. When a user updates data the time is recorded like this:
public HttpResponseMessage PutContent(int id, Content content)
{
if (id != content.ContentId)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
try
{
content.ModifiedDate = DateTime.Now;
content.ModifiedBy = User.Identity.GetUserId();
_uow.Contents.Update(content);
_uow.Commit();
return Request.CreateResponse(HttpStatusCode.OK, content);
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
}
}
When the user looks at the modified time they see what I assume is the server time. Is there a way that I can allow them to see the local time that the change was made?
Note that already I do some formatting but I am not sure if there is a way that I can convert the date and have this matched up with my local users who could be in any location:
<input disabled="disabled" type="text"
value="{{modal.data.modifiedDate | date:'MM/dd/yy HH:mm'}}" />
To start with it is always better to save the dates on server in UTC. So on the server use the method DateTime.UtcNow.
And while sending the data to client, if you are not custom formatting the date, i believe the date send contains the timezone information as well. AngularJS can handle that correct using date filter. See this fiddle http://jsfiddle.net/jHSLe/1/
Assuming the date you are getting is in UTC, you can use the excellent Moment.js to easily convert it to local time as described here:
http://momentjs.com/docs/#/manipulating/local/

Resources