how do i edit the chattile variable in the contructor 'tambah' as shown below:
class ChatCardList extends StatefulWidget {
List<ChatTile> chattile; //EDIT THIS
ChatCardList({Key key, this.chattile}) : super(key: key);
Future<void> _onSocketInfo_newMessage(dynamic data) async {
ChatCardList _data = new ChatCardList.tambah(data);
}
ChatCardList.tambah(String message) {
print("PESAN BARU : " + message);
this.chattile.add(message); //PUSH OBJECT
}
print(chattile); //notting added
#override
_ChatCardListState createState() => new _ChatCardListState(chattile:chattile);
}
why did that happen? is my script wrong, or is there something missing from my code?
many thanks,
Could you go back and check that this is the actual code that is causing your problem.
The code displayed here will not compile at all, so it's hard to say where the real problem is. Alternatively, describe in detail what you are actually trying to achieve.
The ChatCardList.tambah(String message) { constructor does not initialize chattile, so the value of this.chattile in the body should be null. Calling add on that will throw. Otherwise that code is perfectly fine, it is how you add to a list stored in this's chattile variable.
The Future<void> _onSocketInfo_newMessage(dynamic data) async { method creates a new ChatCardList using CharCardList.tambah, but never does anything with it (it doesn't return the value), so nobody will ever see that object or its chattile value.
Also, the print(chattile); code is outside of any function or constructor body, so it is really declaring an abstract method called print which takes a parameter named chattile. Since your class isn't abstract, that should cause a compile-time error.
So, one way to rewrite your program could be:
class ChatCardList extends StatefulWidget {
List<ChatTile> chattile; //EDIT THIS
ChatCardList({Key key, this.chattile}) : super(key: key);
Future<void> _onSocketInfo_newMessage(dynamic data) {
String message = data;
this.chattile.add(message);
}
#override
_ChatCardListState createState() => new _ChatCardListState(chattile: chattile);
}
This code doesn't introduce the tambah constructor, but instead updates the chattile list immediately in the _onSocketInfo_newMessage method. That method still needs to be called from somewhere.
Related
So, by reading the NestJS documentation, I get the main idea behind how the filters work with exceptions.
But from all the code I have seen, it seems like all services always throw HttpExceptions.
My question is: Should the services really be throwing HttpExceptions? I mean, shouldn't they be more generic? And, if so, what kind of Error/Exception should I throw and how should I implement the filter to catch it, so I won't need to change it later when my service is not invoked by a Http controller?
Thanks :)
No they should not. An HttpException should be thrown from within a controller. So yes, your services should expose their own errors in a more generic way.
But "exposing errors" doesn't have to mean "throwing exceptions".
Let's say you have the following project structure :
📁 sample
|_ 📄 sample.controller.ts
|_ 📄 sample.service.ts
When calling one of your SampleService methods, you want your SampleController to know whether or not it should throw an HttpException.
This is where your SampleService comes into play. It is not going to throw anything but it's rather going to return a specific object that will tell your controller what to do.
Consider the two following classes :
export class Error {
constructor(
readonly code: number,
readonly message: string,
) {}
}
export class Result<T> {
constructor(readonly data: T) {}
}
Now take a look at this random SampleService class and how it makes use of them :
#Injectable()
export class SampleService {
isOddCheck(numberToCheck: number): Error | Result<boolean> {
const isOdd = numberToCheck%2 === 0;
if (isOdd) {
return new Result(isOdd);
}
return new Error(
400,
`Number ${numberToCheck} is even.`
);
}
}
Finally this is how your SampleController should look like :
#Controller()
export class SampleController {
constructor(
private readonly sampleService: SampleService
) {}
#Get()
sampleGetResponse(): boolean {
const result = this.sampleService.isOddCheck(13);
if (result instanceof Result) {
return result.data;
}
throw new HttpException(
result.message,
result.code,
);
}
}
As you can see nothing gets thrown from your service. It only exposes whether or not an error has occurred. Only your controller gets the responsibility to throw an HttpException when it needs to.
Also notice that I didn't use any exception filter. I didn't have to. But I hope this helps.
I am attempting to create my first Razor Component in a Blazor Server-side project. The Razor Component is named MyComponent and has a property configured to retrieve its value from input:
MyComponent.razor
[Parameter]
public int Count {get; set;}
I am pulling the count from an injected service configured via IServiceCollection, which looks like this:
public interface ICountingService
{
ValueTask<int> Get();
}
The hosting page, Index.razor looks like the following:
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#Counter.Get()" />
However, I cannot seem to bind the correct value for the Count property.
I get the following error:
cannot convert from 'System.Threading.Tasks.ValueTask<int>' to 'int'
All of the examples I have found for assigning [Parameter] values to Razor Components are synchronous, and the only asynchronous values I have found are for callbacks and methods (not parameters).
Further, searching online did not return anything obvious so I am posting here in hopes of finding an answer.
Note that I am aware of using protected override async Task OnInitializedAsync and storing a value in there, but that seems like a lot of required ceremony compared to the approach above, especially when considering the multiple services and properties that I will ultimately have to bind.
So, how does one assign values from an asynchronous call to a Razor Component [Parameter] property in the way that I would prefer?
The problem is, Counter.Get() isn't an int value; it's a Task that will have an int at some undefined point either now or in the future. So you can't assign its value to something that's expecting an int right now, because that int doesn't necessarily exist yet.
You've already got the answer, and though it "seems like a lot of ceremony", it's really the only way to do this:
Create an int property to hold the value.
Declare an async method
In that method, assign the awaited value of Counter.Get() to the int that's holding the value
Set the component's Count property equal to the int property
It may feel like a lot of ceremony, but you should be grateful. Asynchrony is inherently very complicated, and having async/await available already takes care of about 95% of the hard work for you. If you think this solution is messy, you oughtta see what it would take to get it right without async/await!
Try this.
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#CounterValue" />
#code{
public int CounterValue {get; set;}
protected override async Task OnInitializedAsync()
{
CounterValue = await Counter.Get();
}
}
After #mason-wheeler and #rich-bryant provided their answers, I went to think about this a little more and found my solution, which I have posted here:
https://github.com/Mike-E-angelo/Blazor.ViewProperties
I am calling it a ViewProperty which looks like the following:
public interface IViewProperty
{
ValueTask Get();
}
public sealed class ViewProperty<T> : IViewProperty
{
public static implicit operator ViewProperty<T>(ValueTask<T> instance) => new ViewProperty<T>(instance);
readonly ValueTask<T> _source;
public ViewProperty(ValueTask<T> source) => _source = source;
public T Value { get; private set; }
public bool HasValue { get; private set; }
public async ValueTask Get()
{
Value = await _source;
HasValue = true;
}
public override string ToString() => Value.ToString();
}
You then pair it with a component base type that then iterates through the component's view properties and invokes their respective asynchronous operations:
public abstract class ViewPropertyComponentBase : ComponentBase
{
protected override async Task OnParametersSetAsync()
{
var properties = GetType().GetRuntimeProperties();
foreach (var metadata in properties.Where(x => x.GetCustomAttributes<ParameterAttribute>().Any() &&
typeof(IViewProperty).IsAssignableFrom(x.PropertyType)))
{
if (metadata.GetValue(this) is IViewProperty property)
{
await property.Get().ConfigureAwait(false);
}
}
}
}
A sample razor component that uses the above:
MyComponent.razor
#inherits ViewPropertyComponentBase
#if (Count.HasValue)
{
<p>Your magic number is #Count.</p>
}
else
{
<p>Loading, please wait...</p>
}
#code {
[Parameter]
public ViewProperty<int> Count { get; set; }
}
The resulting use is a clean view with direct bindings and no need for overrides or other additional ceremony:
#page "/"
#inject ICounter Count
<h1>Hello, world!</h1>
Welcome to your new app.
<MyComponent Count="#Count.Count()" />
(NOTE that my posted example and above uses reflection, which is slow. In the actual version of the solution that I am using, I compile the member access as lambda expressions and cache the result. You can find that by starting here if you are brave enough to poke around.)
It feels a bit hacky, but you could do something like this:
<MyComponent Count="#Counter.Get().Result" />
I want to acces a function from another class. A solution would be to initalize the second class in the class I want to access. Like this:
class Calendarsub extends State<Calendar> with SingleTickerProviderStateMixin{
final TableCalendar tableCalendar;
Calendarsub(this.tableCalendar);
When I do this I can acces the functions but the app is not running because the Stateful Widget says: "1 required Argument expected but 0 found."
class Calendar extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return Calendarsub(); // In this bracket must be the argument
// But I don't know which one
}
}
You constructor needs 1 argument - TableCalendar
So, you have to initialize it with this value:
TableCalendar tableCalendar = TableCalendar(); //or somethimg like that
Calendarsub calendar = Calendarsub(tableCalendar);
or make this parameter optional:
class Calendarsub extends State<Calendar> with SingleTickerProviderStateMixin{
TableCalendar tableCalendar;
Calendarsub({this.tableCalendar});
in second case creating will be like:
Calendarsub calendar = Calendarsub(tableCalendar: TableCalendar());
It sounds like you have two classes using the same name
Calendar, a subclass of StatefulWidget, which takes a parameter
Calendar, a State, which doesn't take any parameter
This confuses the compiler. You need to rename so that there's no name conflict anymore.
Suppose I have two sets of controllers in Spring:
/jsonapi1/*
/jsonapi2/*
both of which return objects that are to be interpretted as JSON text.
I'd like some kind of filter to wrap the responses from one set of these controllers so that:
the original response is contained within another object.
For example, if /jsonapi1/count returns:
{"num_humans":123, "num_androids":456}
then the response should be wrapped and returned as follows:
{ "status":0,
"content":{"num_humans":123, "num_androids":456}
}
if an exception happens in the controller, then filter should catch the exception and report it as follows
{ "status":5,
"content":"Something terrible happened"
}
The responses from the other controllers are returned unchanged.
We're currently customizing a MappingJackson2HttpMessageConverter passed to WebMvcConfigurerAdapter.configureMessageConverters in order to perform the above tasks. Works great except that it doesn't seem possible for this approach to be selective about the URLs (or controller classes) it applies to.
Is it possible to apply these kinds of wrappers to individual controller classes or URLs?
Update: Servlet filters look like a solution. Is it possible chose which filter gets applied to which controller methods, or which URLs?
I was struggling on this for multiple days. The solution by #Misha didn't work for me. I was able to finally get this working using ControllerAdvice and ResponseBodyAdvice.
ResponseBodyAdvice allows to inject custom transformation logic on the response returned by a controller but before it is converted to HttpResponse and committed.
This is how my controller method looks:
#RequestMapping("/global/hallOfFame")
public List<HallOfFame> getAllHallOfFame() {
return hallOfFameService.getAllHallOfFame();
}
Now i wanted to add some standard fields around the response like devmessage and usermessage. That logic goes into the ResponseAdvice:
#ControllerAdvice
public class TLResponseAdvice implements ResponseBodyAdvice<Object> {
#Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// TODO Auto-generated method stub
final RestResponse<Object> output = new RestResponse<>();
output.setData(body);
output.setDevMessage("ResponseAdviceDevMessage");
output.setHttpcode(200);
output.setStatus("Success");
output.setUserMessage("ResponseAdviceUserMessage");
return output;
}
}
The entity classes look like this:
#Setter // All lombok annotations
#Getter
#ToString
public class RestResponse<T> {
private String status;
private int httpcode;
private String devMessage;
private String userMessage;
private T data;
}
#Entity
#Data // Lombok
public class HallOfFame {
#Id
private String id;
private String name;
}
To handle exceptions, simply create another ControllerAdvice with ExceptionHandler. Use the example in this link.
Advantages of this solution:
It keeps your controllers clean. You can support any return type from your controller methods.
Your controller return type class does not need to extend some base class as required by the AOP approach.
You do not need to hack your way through Spring filters by using HttpServletResponseWrappers. They come up with a performance penalty.
EDIT - 17th September 2019
To handle exceptions use #ExceptionHandler. Refer code below.
#ExceptionHandler(Exception.class)
#ResponseBody
public MyResponseEntity<Object> handleControllerException(HttpServletRequest request, Throwable ex) {
// default value
int httpCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
if(ex instanceof ResourceNotFoundException) {
httpCode = HttpStatus.NOT_FOUND.value();
}
...
}
The way I understand your question, you have exactly three choices.
Option #1
Manually wrap your objects in simple SuccessResponse, ErrorResponse, SomethingSortOfWrongResponse, etc. objects that have the fields you require. At this point, you have per-request flexibility, changing the fields on one of the response wrappers is trivial, and the only true drawback is code repetition if many of the controller's request methods can and should be grouped together.
Option #2
As you mentioned, and filter could be designed to do the dirty work, but be wary that Spring filters will NOT give you access to request or response data. Here's an example of what it might look like:
#Component
public class ResponseWrappingFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) {
// Perform the rest of the chain, populating the response.
chain.doFilter(request, response);
// No way to read the body from the response here. getBody() doesn't exist.
response.setBody(new ResponseWrapper(response.getStatus(), response.getBody());
}
}
If you find a way to set the body in that filter, then yes, you could easily wrap it up. Otherwise, this option is a dead end.
Option #3
A-ha. So you got this far. Code duplication is not an option, but you insist on wrapping responses from your controller methods. I'd like to introduce the true solution - aspect-oriented programming (AOP), which Spring supports fondly.
If you're not familiar with AOP, the premise is as follows: you define an expression that matches (like a regular expression matches) points in the code. These points are called join points, while the expressions that match them are called pointcuts. You can then opt to execute additional, arbitrary code, called advice, when any pointcut or combination of pointcuts are matched. An object that defines pointcuts and advice is called an aspect.
It's great for expressing yourself more fluently in Java. The only drawback is weaker static type checking. Without further ado, here's your response-wrapping in aspect-oriented programming:
#Aspect
#Component
public class ResponseWrappingAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void anyControllerPointcut() {}
#Pointcut("execution(* *(..))")
public void anyMethodPointcut() {}
#AfterReturning(
value = "anyControllerPointcut() && anyMethodPointcut()",
returning = "response")
public Object wrapResponse(Object response) {
// Do whatever logic needs to be done to wrap it correctly.
return new ResponseWrapper(response);
}
#AfterThrowing(
value = "anyControllerPointcut() && anyMethodPointcut()",
throwing = "cause")
public Object wrapException(Exception cause) {
// Do whatever logic needs to be done to wrap it correctly.
return new ErrorResponseWrapper(cause);
}
}
The final result will be the non-repeating response wrapping that you seek. If you only want some or one controller receive this effect, then update the pointcut to match methods only within instances of that controller (rather than any class holding the #Controller annotation).
You'll need to include some AOP dependencies, add the AOP-enabling annotation in a configuration class, and make sure something component-scans the package this class is in.
Simplest way i manage custom responses from controllers is by utilising the Map variable.
so your code ends up looking like:
public #ResponseBody Map controllerName(...) {
Map mapA = new HashMap();
mapA.put("status", "5");
mapA.put("content", "something went south");
return mapA;
}
beauty of is is that you can configure it any thousand ways.
Currently i use for object transmition, custom exception handling and data reporting, too easy.
Hope this helps
I am also using AOP with #Around. Developed a custom annotation and using that for point cut. I am using a global Response. It has the status, Message and data which is of type List of type
List <? extends parent> dataList
( which can solve your class cast exception). All the entities extends this Parent class. This way I can set all the data into my List.
Also I am using the message key as param with the custom annotation and setting it in action.
Hope this helps.
I'm using EF 4.1 Code First. I have an entity defined with a property like this:
public class Publication
{
// other stuff
public virtual MailoutTemplate Template { get; set; }
}
I've configured this foreign key using fluent style like so:
modelBuilder.Entity<Publication>()
.HasOptional(p => p.Template)
.WithMany()
.Map(p => p.MapKey("MailoutTemplateID"));
I have an MVC form handler with some code in it that looks like this:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
In this case, we're updating an existing Publication entity, so we're going through the else path. When the _unitOfWork.Commit() fires, an UPDATE is sent to the database that I can see in SQL Profiler and Intellitrace, but it does NOT include the MailoutTemplateID in the update.
What's the trick to get it to actually update the Template?
Repository Code:
public virtual void Update(TEntity entity)
{
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual TEntity Get(int id)
{
return _dbSet.Find(id);
}
UnitOfWork Code:
public void Commit()
{
_dbContext.SaveChanges();
}
depends on your repository code. :) If you were setting publication.Template while Publication was being tracked by the context, I would expect it to work. When you are disconnected and then attach (with the scenario that you have a navigation property but no explicit FK property) I'm guessing the context just doesn't have enough info to work out the details when SaveChanges is called. I'd do some experiments. 1) do an integration test where you query the pub and keep it attached to the context, then add the template, then save. 2) stick a MailOutTemplateId property on the Publicaction class and see if it works. Not suggesting #2 as a solution, just as a way of groking the behavior. I"m tempted to do this experiment, but got some other work I need to do. ;)
I found a way to make it work. The reason why I didn't initially want to have to do a Get() (aside from the extra DB hit) was that then I couldn't do this bit of AutoMapper magic to get the values:
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
However, I found another way to do the same thing that doesn't use a return value, so I updated my method like so and this works:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = _publicationRepository.Get(publicationEditViewModel.Id);
_mappingEngine.Map(publicationEditViewModel, publication);
// publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
I'm injecting an IMappingEngine now into the class, and have wired it up via StructureMap like so:
For<IMappingEngine>().Use(() => Mapper.Engine);
For more on this, check out Jimmy's AutoMapper and IOC post.