0727 - redux action 500, xml to POJO, ZonedDateTime, ag-grid overlay/copy, jest synchronize

1. redux async action handle non-200

It seems though the call backend get 500, the redux async will not goes into catch block automatically. For example, It can go into catch because it cannot parse Json of the error message, but not because of the backend is 500.

Seems only frontend exceptions will go to the catch block, and backend exceptions need to process by checking response.ok:

Retrieve data from a ReadableStream object?

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    return response.text();  // 
  }).then(function(data) {
    console.log(data); // this will be a string
  });

For me, if response.status is not 200, I can use response.text() to read error message.
It’s also to build error message into json, and handle it like this:

Why does .json() return a promise?
In addition to the above answers here is how you might handle a 500 series response from your api where you receive an error message encoded in json:

callApi(url) {
  return fetch(url)
    .then(response => {
      if (response.ok) {
        return response.json().then(response => ({ response }));
      }

      return response.json().then(error => ({ error }));
    })
  ;
}

2. javascript fetch - Failed to execute ‘json’ on ‘Response’: body stream is locked

you only can consume response.json() or response.text() or … once.

3. How to check if JavaScript object is JSON

You can use Array.isArray to check for arrays. Then typeof obj == ‘string’, and typeof obj == ‘object’.

if (typeof p == 'string')

4. Java Read XML

4.1 Java DOM Parser Example

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("employees.xml"));
document.getDocumentElement().normalize();
NodeList nList = document.getElementsByTagName("employee");
...

4.2 JAXB Read XML to Java Object Example

From xml string:

jaxbContext = JAXBContext.newInstance(Employee.class);              
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Employee employee = (Employee) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));

if String too long, can read from file as a String.

From xml file:

jaxbContext = JAXBContext.newInstance(Employee.class);              
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Employee employee = (Employee) jaxbUnmarshaller.unmarshal(xmlFile);

4.3 I can’t understand why this JAXB IllegalAnnotationException is thrown:

  • Annotate the Field with @XmlAccessorType(XmlAccessType.FIELD), but originally I was using @XmlAccessorType(XmlAccessType.PROPERTY) as some tutorial.
  • XmlAccessType

4.4 从xml读进来的POJO的inner class是null

主要是加了@XMLAttribute就能发现那些field,inner class就不是null了

4.5 我的实现

xml file:

<?xml version="1.0" ?>
<myResponse>
<myList>
<element><filename>abc.pdf</filename><address>123</address></element>
<element><filename>abc.pdf</filename><address>123</address></element>
</myList>
</myResponse>

For POJO class:

@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name="myResponse") // the name from xml file
@XmlAccessorType(XmlAccessType.FIELD)
public class MyResponse implements Serializable {
	@XmlElement(name = "myList", required=true)
	@JsonProperty("SubResponse")
	private MyList myList;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name="myList") // the name from xml file
@XmlAccessorType(XmlAccessType.FIELD)
public class MyResponse implements Serializable {
	@XmlElement(name = "element", required=true)
	@JsonProperty("someListName")
	private List<Element> myList;
}


@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name="element") // the name from xml file
@XmlAccessorType(XmlAccessType.PROPERTY)  // maybe FIELD also work...
public class Element implements Serializable {

	private String fileName;
	private String address;
	
}

For xml Reader:

public static void main(String[] args) {
	try{
		File xmlFile = new File("absolute/path/file.xml");
		// or (in case string is too long exception):
		// String filePath = "absolute/path/file.xml";
		// Stream strean = Files.lines(Paths.get(filePath), StandardCharsets.UTR_8);
		// StringBuilder sb = new StringBuilder();
		// String xmlString = sb.toString();
		
		JAXBContext jaxbContext = JAXBContext.newInstance(MyResponse.class);
		Unmarshaller jaxbUnmarshaller = jaxbContext.createUnMarshaller();
		MyResponse myResponse = (MyResponse) jaxbUnmarshaller.unmarshal(xmlFile);
		// or, for String:
		// MyResponse myResponse = (MyResponse) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));

		// now we already get the myResponse class, then we can do other process
		List<Element> attribute1List = myResponse.getMyList()....
	}
}

写给自己:Actually I have 2 ways for get all field names:

  1. first is copy the lex result to xml file, and read it as POJO, but the file is too slow when copy paste from lex url to xml…
  2. second is expose an endpoint, which will go over all fields… it’s faster but cannot have access to different env when run in local…

5. Ag-grid overlay

You may never use these methods, as the grid manages the overlays for you.
When the table is first initialized, the loading panel is displayed if rowData is set to null or undefined. When the api function setRowData is called, the loading panel is hidden.

但是我需要在data变化的时候,也call这个overlay,所以就自己explicitly地call了一下:

// show 'loading' overlay
gridOptions.api.showLoadingOverlay()

// clear all overlays
gridOptions.api.hideOverlay()

6. how to copy the values present in ag-grid

enableCellTextSelection=true

7. 想在浏览器里用类似regex的搜索…

https://superuser.com/questions/723865/chrome-how-to-search-a-keyword-with-excluding-specific-keyword-without-changing
但当时我的chrome好像被proxy block了,这个我用不了。
开发者模式下也能用regex搜索,但是regex太难写了…

8. wrapper.find with id in enzyme

<button className="Selections" id="increment" onClick={this.incrementPage}>Next</button>
const incrementPage = wrapper.find('#increment')

9. jest it and describe execution order?

经过我的一翻尝试,jest的it之间是有一定顺序执行的,但也不保证是synchronize的,而describe其实也不一定是synchronized的。虽然很多地方都说describe是不会被多线程同时运行的,但我的情况让我感觉这个说法不全对。。。

当时有个synchronize的错,由于IntelliJ run all test不是synchronize的而是多线程的,导致单独run一个it是正确的(注释掉其它),所有it模块一起run就不正确。即使我把它们分成两个describe也不行。(但是我若是调换一下两个describe的位置说不定可以)

但是把那个it调到前面,就可以了,大概确保了它可以被最先run,蜜汁顺序?但由于那个it在后面就不work了,所以我们也不能说it之间是synchronize的,依次执行的,假如是synchronize的,不管啥顺序应该都可以才对。

那个it没有用spy on useSelector then mockReturn,其它的三个都用了,mockReturn的value []总是影响那个没有用spy on,而是直接给store initialize的。

代码如下:

it("it-1", () => {
	const wrapper = getWrapperWithData(); // use mount, pass success state which has data into mockstore
	const expectedData = [{key1:"val1", ...}];
	const data = wrapper.find(AgGridReact).prop('rowData');
	expect(data).toEqual(expectedData);
});

but because of the spy.mockReturnValue in another “it”, the data will be [] if I put “it-1” after “it-2”… even separate them into 2 describe also not work… kind wired actually…

it("it-2", () => {
	const spy = jest.spyOn(Redux, 'useSelector');
	spy.mockReturnValue([]);
	const wrapper = getWrapper(); // use mount, pass initial state which does not have data, into mockstore
	...
});

10. Javascript: Convert timestamp to human readable date?

const date = new Date(timestamp).toDateString();
console.log(date);

How can I delete the first word from a line?

var original = "Mon 25-Jul-2011";
var result = original.substr(original.indexOf(" ") + 1);

11. Get Offset between local time and UTC time

the Date class only has millisecond precision. It cannot store higher precision.
Timestamp has nanosecond precision. Both java.sql.Date and java.util.Date have only millisecond precision. Once you bring either Date into the game, you will lose precision.

11.1 method I tried but not used

Convert Date String into Epoch in Java

Local Time to UTC in Java

How do you convert a UTC timestamp to local time?
Date has no timezone and internally stores in UTC

11.2 Confusion with Java Time parsing UTC

LocalDateTime:
So it’s explicit purpose is just to represent a date and time without a time-zone. It’s porpose is not to represent a date and time in the local time zone.

So for your purposes you need a ZonedDateTime with ZoneId.systemDefault().
Or use Instant.

11.3 What exactly does the T and Z mean in timestamp?

The T doesn’t really stand for anything. It is just the separator that the ISO 8601 combined date-time format requires. You can read it as an abbreviation for Time.

11.4 GMT is a time zone and UTC is a time standard.

11.5 frontend / backend timezone

when use frontend, the time normally, at least for me is by default is my computer’s time zone… The data stored in the server may use another time zone’s timestamp, but as said before, Date has no time zone, it’s by default UTC… java currentTimeMillis will also be UTC time.

11.6 我的最终方法

With java8 now, you can use

Integer offset  = ZonedDateTime.now().getOffset().getTotalSeconds();

to get the current system time offset from UTC. Then you can convert it to any format you want. Found it useful for my case. Example :
https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

assertEquals, 为啥自动给expected加上“ ”.

public String convertor(ZonedDateTime zonedDateTime) {

	Integer offset = zonedDateTime.getOffset().getTotalSeconds();
	if (offset != 0) {
		int sign = offset / Math.abs(offset);
		...
		int hh = offset/3600;
		int mm = (offset - hh * 3600) / 60;
		...
	}
	...
	
}


ZonedId zoneIdJapan = ZoneId.of("Japan");
ZonedDateTime zonedDateTimeJapan = ZonedDateTime.now(zoneIdJapan);
ZonedDateTime zonedDateTimeLocal = ZonedDateTime.now();
ZonedDateTime zonedDateTimeGMT = ZonedDateTime.now("UTC");

assertEquals(convertor(zonedDateTimeJapan), "+12:00");
assertEquals(convertor(zonedDateTimeLocal), "-xx:00");
assertEquals(convertor(zonedDateTimeGMT), "");

这样也可:

TimeZone localTimeZone = TimeZone.getDefault();
long now = System.currentTimeMillis();
long diff = localTimeZone.getOffset(now);
String offset = String.format("%02d:%02d", Math.abs(diff/3600000), Math.abs(diff/60000) % 60));

你可能感兴趣的:(One,week,Learning,Notes)