Code-First REST APIs Followup: OpenAPI

Aug 26, 2022, 11:04 AM

Tags: jakartaee
  1. Code-First REST APIs With XPages Jakarta EE Support
  2. Code-First REST APIs Followup: OpenAPI

In yesterday's post, I gave a two-file example of writing a basic CRUD REST API for NSF documents. In that post, I casually mentioned that one of the side benefits of this approach would have to wait until I fixed an open bug.

Well, I fixed that bug not long after making that post, so now I can detail what that is.

But just before I do that, I should mention that I added an "examples" directory to the project repository, where I plan to put examples like this in on-disk-project form, without the baggage of the test-suite example NSFs in the main tree: https://github.com/OpenNTF/org.openntf.xsp.jakartaee/tree/develop/examples. Anyway, back to what I fixed up here.

One of the neat little side features that the framework brings in is MicroProfile OpenAPI, which automatically generates OpenAPI specifications for your REST services based on your code. Depending on your workflow, this can be tremendously convenient. OpenAPI, being a widely-supported spec, has tons of tools available, and you can use this when integrating other applications with yours, or when working in a multi-tiered development team. For example, if the UI portion of your app is being developed separately from the back end, you could hand off the OpenAPI file to the other developer(s) and they will have the information they need to write against your services. And, since it's generated from the code and not manually, it has the benefit of being inherently consistent with the current design of the app.

Default Output

By default, based on how the app worked when we left it yesterday, going to "foo.nsf/xsp/app/openapi.yaml" will get you this output:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
---
openapi: 3.0.3
info:
  title: Jakarta Code-First REST
servers:
- url: http://some.server/foo.nsf/xsp/app
paths:
  /employees:
    get:
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Employee'
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Employee'
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Employee'
  /employees/{id}:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Employee'
    put:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Employee'
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Employee'
    delete:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "204":
          description: No Content
components:
  schemas:
    Employee:
      required:
      - name
      - title
      - department
      type: object
      properties:
        id:
          type: string
        name:
          minLength: 1
          type: string
          nullable: false
        title:
          minLength: 1
          type: string
          nullable: false
        department:
          minLength: 1
          type: string
          nullable: false
        age:
          format: int32
          minimum: 1
          type: integer

This includes all of the operations we defined in the rest.EmployeesResource class as well as the definition of the model.Employee entity class. Additionally, it picked up on our Bean Validation annotations, and so all of the @NotEmpty properties are marked as being non-null and non-empty strings, while the age has a minimum of 1, as coded.

Expanding the Definition

That, on its own, is pretty useful, and it will automatically adapt to any code changes you make. However, you can go further.

Versions

For example, while having the file as it is will work for development, you'll want to give it a version when it goes into production, so that any API consumers can know when it's expected that the API changed. There are two ways to do this with this project. If you have a $TemplateBuild shared field with a template version, then the code will pick up on that. Alternatively, you can specify configuration properties via MicroProfile Config. To do that, create a new file in the "Code/Java" directory of the project in the Package Explorer view in Designer named "microprofile-config.properties" within a directory named "META-INF":

Creating a microprofile-config.properties file

If you don't have a Package Explorer pane, you can add it by going to Window and then either switching to the "XPages" perspective or going to "Show Eclipse Views" and picking it from there. To add the folder and then the file, you can right-click the "Code/Java" folder there and then going to "New" - "Other..." and picking each in turn.

Once you have that file open, add a line like this:

1
mp.openapi.extensions.smallrye.info.version=1.0.1

("SmallRye" is the name of several MicroProfile spec implementations)

Then save. Now, when you open the OpenAPI spec, it'll start like this:

1
2
3
4
5
---
openapi: 3.0.3
info:
  title: Jakarta Code-First REST
  version: 1.0.1

Now, as long as you update this for API changes or use a $TemplateBuild field, your OpenAPI will be nicely versioned. As a nice bonus, if you build your NSF using the NSF ODP Tooling project, it can add the Maven version to $TemplateBuild by default, so you don't have to worry about manual updates.

Endpoint Descriptions

Next, while all of our endpoints are listed, it'd be good to add some additional detail. While they're more-or-less clear now, it'll get less so as the app grows. This is generally done via annotations - there are a bunch of them, but we'll focus on just a few for now.

We'll start with a basic one: adding a description to the endpoint that lists all Employees. To do this, go back to rest.EmployeeResource and add an annotation of type org.eclipse.microprofile.openapi.annotations.Operation:

1
2
3
4
5
6
@GET
@Produces(MediaType.APPLICATION_JSON)
@Operation(description="Retrieves a list of all employee entities in the data store")
public List<Employee> get() {
	return employees.findAll(Sorts.sorts().asc("name")).collect(Collectors.toList());
}

Once you add that, then that part of the OpenAPI spec will read:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
paths:
  /employees:
    get:
      description: Retrieves a list of all employee entities in the data store
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Employee'

Better by one step. The @Operation annotation itself has a couple more properties, which let you specify an operationId (very useful for code generated from the spec, so I advise doing it in a fully-fledged app) or marking the operation as "hidden", so it won't show up in the output at all.

Model Annotations

Next up, we'll add some descriptive information to the Employee model itself. For this, we'll go back to model.Employee and start adding annotations of type org.eclipse.microprofile.openapi.annotations.media.Schema:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Schema(description = "Represents an individual employee within the system")
@Entity
public class Employee {
	/* snip */
	
	private @Id String id;
	@Schema(description="The employee's full name", example="Foo Fooson")
	private @Column @NotEmpty String name;
	@Schema(description="The employee's job title", example="CTO")
	private @Column @NotEmpty String title;
	@Schema(description="The name of the employee's current department within the company", example="IT")
	private @Column @NotEmpty String department;
	@Schema(description="The employee's current age", example="80")
	private @Column @Min(1) int age;

	/* snip */
}

The @Schema annotation is usable in a lot of situations and has a lot of options, but these will suffice for now. Once we add these, our OpenAPI spec expands in the components section to this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
components:
  schemas:
    Employee:
      description: Represents an individual employee within the system
      required:
      - name
      - title
      - department
      type: object
      properties:
        id:
          type: string
        name:
          description: The employee's full name
          minLength: 1
          type: string
          example: Foo Fooson
          nullable: false
        title:
          description: The employee's job title
          minLength: 1
          type: string
          example: CTO
          nullable: false
        department:
          description: The name of the employee's current department within the company
          minLength: 1
          type: string
          example: IT
          nullable: false
        age:
          format: int32
          description: The employee's current age
          minimum: 1
          type: integer
          example: 80

Now, anyone reading this (or interpreting it with a tool) will have just a bit more information about it. In this case, the descriptions don't add much, but you can imagine expanding this to cover your business specific business rules for formatting, internal codes, etc..

Swagger

Though there's a lot more that you can do to expand the OpenAPI generation, I'll leave it there for now. I'll finish up here with one of the more straightforward benefits you get from this: using Swagger UI. Swagger UI is a tremendously-popular tool for visualizing (and, to an extent, working with) OpenAPI specifications. You can download Swagger UI yourself (to run locally or put in your NSF) or use the live demo, which runs in your browser.

If you want to use the live demo, you can enable CORS in the microprofile-config.properties file created earlier, setting rest.cors.enable to true and rest.cors.allowedOrigins to *.

Once you have it accessible, you can point Swagger UI to your URL, like "http://some.server/foo.nsf/xsp/app/openapi.yaml", and it'll generate a nice summary:

Screenshot of Swagger UI pointing at our app

You can imagine either handing that off to your front-end developer or using it yourself when working on the client part of your system. As you expand your spec - say, adding @Tag to categorize your resources - the UI will expand to reflect it as well.

Conclusion

I'm quite fond of the MicroProfile OpenAPI spec here - it's easy to use and you don't have to worry about the fiddly work of actually generating the spec. Additionally, it's an excellent example of the kind of benefits you get from building on top of Jakarta and MP specifications: because they're built by the active involvement and many companies and with an eye towards interoperability, you automatically get to use tools like Swagger UI or OpenAPI Generator that have no knowledge of Domino. You're rowing in the same direction as lots of others.

In the short term, I plan to update the examples section of the project Git repo with the newer version of these classes, and then follow up by putting the "GitHub issues" client code I wrote for my recent OpenNTF presentation in as another example. Once I do the latter, I'll make sure to post about it as well.

Commenter Photo

RonaldIdera - Sep 28, 2022, 10:21 PM

<a href=https://izi-ege.ru/index.php?r=egerus/view&id=14>https://izi-ege.ru/index.php?r=rus/view&id=25

Commenter Photo

hygatsic - Sep 29, 2022, 9:03 AM

На сайте https://catcasino-site.ru/ представлен содержательный и интересный обзор казино Кэт. Важным моментом является то, что оно лицензионное, а потому ведет свою деятельность официально. Преимуществом онлайн-заведения является то, что оно предлагает щедрую бонусную систему, лояльные условия для каждого клиента, а особенно новичков. Именно поэтому многие выбирают эту площадку, которая радует условиями. Но сыграть в казино могут только те, кому исполнилось 18 лет. При этом вывод средств происходит максимально оперативно.

Commenter Photo

Robertamili - Sep 29, 2022, 6:28 PM

вавада казино официальный сайт Мы тщательно проверяем каждое казино, представленное на нашем сайте, чтобы убедиться, что наши клиенты получают наилучший опыт. Вывести. Проверяя казино с самым низким минимальным депозитом, мы обращаем внимание на процесс вывода средств с определенного сайта. Мы выясняем, как получить свои деньги, и сколько именно вы можете вывести с помощью этого казино

Commenter Photo

Williamcip - Sep 29, 2022, 11:45 PM

Всякому начинающему гитаристу очень важно регулярно упражняться на гитаре. Для этого существуют особые ресурсы с разборами песен, например, сайт akkords.pro. Здесь вы найдёте правильные подборы аккордов для гитары для множества знакомых вам песен, которые прекрасно подойдут для обучения начинающим гитаристам.

Commenter Photo

Tysonbok - Sep 30, 2022, 5:04 AM

Любому новичку очень важно систематически практиковаться на гитаре. Для этих целей есть особые ресурсы с подборами аккордов, например, сайт fcgsen. Здесь вы найдёте разборы для кучи знаменитых композиций, которые прекрасно подойдут для обучения новичкам.

Commenter Photo

Tysonbok - Sep 30, 2022, 6:55 AM

Всякому новичку чрезвычайно важно постоянно заниматься на гитаре. Для этих целей существуют специализированные онлайн-ресурсы с подборами аккордов, например, сайт km. Здесь вы найдёте правильные подборы аккордов для кучи знаменитых песен, которые подойдут для изучения начинающим гитаристам.

Commenter Photo

Tysonbok - Sep 30, 2022, 8:43 AM

Каждому новичку крайне важно регулярно заниматься на гитаре. Для этого существуют особые сайты с подборами аккордов, например, сайт ya-poyu. Здесь есть правильные подборы аккордов для множества известных композиций, которые отлично подойдут для изучения новичкам.

Commenter Photo

Tysonbok - Sep 30, 2022, 10:32 AM

Любому новичку крайне важно систематически практиковаться на гитаре. Для этих целей существуют специальные сайты с разборами песен, например, сайт pritone. Тут есть разборы для множества знакомых вам песен, которые прекрасно подойдут для обучения начинающим гитаристам.

Commenter Photo

Tysonbok - Sep 30, 2022, 2:17 PM

Всякому начинающему гитаристу крайне важно систематически упражняться на гитаре. Для этого существуют специализированные ресурсы с разборами песен, например, сайт legav. Тут есть правильные подборы аккордов для множества известных композиций, которые подойдут для обучения новичкам.

Commenter Photo

RaymondNip - Sep 30, 2022, 8:42 PM

Каждому новичку чрезвычайно важно систематически упражняться на гитаре. Для этих целей существуют особые сайты с разборами песен, например, сайт guitar-geek.ru. Тут вы найдёте разборы для множества популярных композиций, которые прекрасно подойдут для обучения новичкам.

Commenter Photo

RaymondNip - Sep 30, 2022, 9:31 PM

Всякому начинающему гитаристу очень важно систематически заниматься на гитаре. Для этого существуют специализированные ресурсы с подборами аккордов, например, сайт russhanson. Тут вы найдёте подборы аккордов для кучи знакомых вам композиций, которые прекрасно подойдут для изучения новичкам.

Commenter Photo

odtiabon - Sep 30, 2022, 10:48 PM

На сайте https://nnvuti.pro/ предлагается сыграть в любопытные игры, особенность которых в том, что вы, в случае выигрыша, получите реальные деньги. При этом они моментально окажутся на вашем счете. Но для того, чтобы избежать мошеннических схем, необходимо играть только на официальном сайте. Важным моментом является то, что здесь отсутствуют какие-либо комиссии, а при регистрации вам полагается бонус, который вы потратите на свое усмотрение. Все выплаты производятся в течение 24 часов и независимо от платежной системы.

Commenter Photo

RaymondNip - Sep 30, 2022, 11:10 PM

Всякому новичку чрезвычайно важно систематически упражняться на гитаре. Для этих целей существуют специальные сайты с подборами аккордов, например, сайт akkord-guitar. Здесь вы найдёте правильные подборы аккордов для гитары для массы известных композиций, которые подойдут для изучения новичкам.

Commenter Photo

RaymondNip - Oct 1, 2022, 12:00 AM

Всякому новичку чрезвычайно важно регулярно практиковаться на гитаре. Для этих целей существуют специальные онлайн-ресурсы с разборами песен, например, сайт russhanson. Здесь есть правильные подборы аккордов для кучи знакомых вам песен, которые подойдут для обучения начинающим гитаристам.

Commenter Photo

RaymondNip - Oct 1, 2022, 2:32 AM

Каждому начинающему гитаристу крайне важно регулярно заниматься на гитаре. Для этого есть специальные сайты с разборами песен, например, сайт makrab. Тут есть подборы для множества знакомых вам песен, которые подойдут для обучения новичкам.

Commenter Photo

thalfrtax - Oct 1, 2022, 4:55 AM

На сайте https://takerr.pro/ вы сможете сыграть в популярную среди азартных пользователей игру, которая точно понравится всем любителям развлечений. Вас ожидает огромное количество режимов, которые добавят только остроты и зрелищности. И самое главное, что перед вами исключительно топовые приложения с реальным выводом средств. Вас ожидает огромное количество режимов, а также тактик, которые помогут заработать неплохие средства на своем умении. Все это и многое другое ожидает вас на портале.

Commenter Photo

RaymondNip - Oct 1, 2022, 6:37 AM

Всякому начинающему гитаристу важно постоянно практиковаться на гитаре. Для этих целей есть особые онлайн-ресурсы с подборами аккордов, например, сайт pep-see. Здесь вы найдёте правильные подборы аккордов для гитары для множества популярных композиций, которые подойдут для обучения начинающим гитаристам.

Commenter Photo

MorrisHic - Oct 1, 2022, 10:18 AM

https://lastdemo.primepix.ru/club/user/621/blog/3309/ http://www.rockarchive.ru/forum/index.php?act=ST&f=20&t=11816 http://www.czpp.ru/club/user/58122/blog/4842/

Commenter Photo

aroutlieda - Oct 1, 2022, 11:13 AM

На сайте https://ttrix.pro/ вы сможете сыграть в честные игры, которые выплачивают реальные средства, причем максимально быстро – всего в течение 24 часов. Попытайте удачу на официальном сайте. Играйте только здесь, чтобы не попасться на удочку мошенников. Иначе вы рискуете потерять все свои деньги. На этом портале вас ожидают промокоды, а также раздачи. И самое главное, что игры интересные, авторские и представлены лучшими разработчиками. Заходите сюда регулярно, если желаете приподнять денег или получить больше адреналина.

Commenter Photo

RaymondNip - Oct 1, 2022, 11:41 AM

Всякому новичку чрезвычайно важно регулярно заниматься на гитаре. Для этих целей существуют специализированные ресурсы с подборами аккордов, например, сайт volga. Здесь вы найдёте правильные подборы аккордов для гитары для множества знакомых вам композиций, которые подойдут для изучения новичкам.

Commenter Photo

RonaldIdera - Oct 1, 2022, 2:05 PM

<a href=http://dobroe-serdce.ucitizen.ru/bitrix/rk.php?goto=http://izi-ege.ru>http://dobroe-serdce.ucitizen.ru/bitrix/rk.php?goto=http://izi-ege.ru

Commenter Photo

afacnsar - Oct 3, 2022, 12:05 AM

Картинки, раскраски, шаблоны, трафареты, поделки все это для развития вашего ребенка. Детям свойственно создавать что-то новое и необычное. Они легко двигаются вперед в плане развития и познания окружающего их мира. Помогите ребенку освоить творческое пространство с таким цифровым контентом. Из самой простой вещи ребенок может нафантазировать целый мир. Наш цифровой контент на сайте https://tozpat.ru/ помогает развить воображение вашего ребенка. Обеспечьте ребенка нашими бесплатными материалами для формирования нестандартного подхода, что требует любое творчество

Commenter Photo

MorrisHic - Oct 3, 2022, 2:35 AM

http://www.subarulegacy.ru/forum/index.php?showtopic=61301 http://www.forumdacha.ru/forum/viewtopic.php?p=173668#173668 http://beauty.net.ru/forum/messages/forum13/topic178503/message714797/?result=new#message714797

Commenter Photo

MorrisHic - Oct 3, 2022, 10:13 AM

http://forum.webmvc.com/index.php?/topic/56692-отличное-пин-ап-казино/ http://бор55.рф/communication/blog/acontinent/otlichnoe-pin-ap-kazino.php http://old.kakdelat.ru/company/personal/user/2647/blog/3149/

Commenter Photo

RonaldIdera - Oct 3, 2022, 11:50 AM

<a href=http://it-universe.org/bitrix/redirect.php?goto=http://izi-ege.ru>http://it-universe.org/bitrix/redirect.php?goto=http://izi-ege.ru

Commenter Photo

antasdig - Oct 3, 2022, 12:44 PM

На сайте https://1upi-x.me/ вы сможете попытать свою удачу и выиграть деньги, сыграв в рулетку, лесенку, кейсы на деньги. И самое главное, что система работает специально для вас, а это значит, что выигранные деньги вы получите сразу же, нет проблем с выводом. Делайте ставки на спорт и выигрывайте. Здесь и сам процесс невероятно интересный и увлекательный, а потому точно вам понравится. Заходите на сайт регулярно, чтобы попытать свою удачу. Для новичков и всех игроков действуют лояльные условия игры, а также интересная бонусная система.

Commenter Photo

vilfulzop - Oct 3, 2022, 1:01 PM

На сайте https://m.kinotik.us представлены различные фильмы, сериалы в огромном многообразии. Их вы сможете скачать на свой мобильный телефон и начать просматривать в любое, наиболее комфортное время и тогда, когда стало скучно, одиноко. Все кино в высоком разрешении, с объемным звуком. А для того, чтобы подобрать идеальный вариант, необходимо воспользоваться фильтром. Есть как новинки, так и любимые всеми фильмы, которые можно пересматривать раз за разом. Имеются и новости из мира кино - ознакомьтесь с ними сейчас.

Commenter Photo

MorrisHic - Oct 3, 2022, 4:28 PM

http://fabnews.ru/forum/showthread.php?p=39895#post39895 http://forwoman.lifeforums.ru/viewtopic.php?id=8143#p16174 http://php.com.ua/blog/topic/107263/

Commenter Photo

hygatsic - Oct 3, 2022, 7:09 PM

На сайте https://catcasino-site.ru/ представлен содержательный и интересный обзор казино Кэт. Важным моментом является то, что оно лицензионное, а потому ведет свою деятельность официально. Преимуществом онлайн-заведения является то, что оно предлагает щедрую бонусную систему, лояльные условия для каждого клиента, а особенно новичков. Именно поэтому многие выбирают эту площадку, которая радует условиями. Но сыграть в казино могут только те, кому исполнилось 18 лет. При этом вывод средств происходит максимально оперативно.

Commenter Photo

MorrisHic - Oct 3, 2022, 10:09 PM

https://cleverlend.ru/topic-t1650.html http://borderforum.ru/viewtopic.php?f=7&t=4988 https://www.birzha-othodov.ru/club/user/17102/blog/3094/

Commenter Photo

enlokoClord - Oct 4, 2022, 1:15 AM

На сайте https://catcasino-bonus1.ru/ имеется обзор самого популярного на сегодняшний день казино Кэт, которое не перестает радовать постоянных пользователей регулярными акциями, щедрой бонусной системой, а также быстрыми выплатами. При этом выигрыш приходит на счет моментально, нет необходимости ждать по нескольку дней. Заведение имеет лицензию, а потому ему точно можно доверять. Многие постоянные игроки оставили об этом клубе положительные отзывы, потому как он старается для своих гемблеров.

Commenter Photo

suppdMut - Oct 4, 2022, 3:13 AM

На сайте https://brillxcc.ru/ вы сможете получить всю необходимую информацию, которая касается новой игровой площадки Brillx. Это лицензионное онлайн-казино, которое предлагает огромный выбор развлечений на самый взыскательный вкус. Кроме того, предусмотрена система лояльности, щедрые бонусы и все то, что сделает игру более зрелищной, захватывающей и интересной. И самое главное, что средства выводятся регулярно, без обмана и задержек. А это существенный плюс данного заведения. Важно то, что софт лицензионный и проверенный, а потому играть – одно удовольствие.

Commenter Photo

RonaldIdera - Oct 4, 2022, 10:11 AM

<a href=http://homesystems.ru/bitrix/rk.php?goto=http://izi-ege.ru>http://homesystems.ru/bitrix/rk.php?goto=http://izi-ege.ru

Commenter Photo

apibiAtory - Oct 4, 2022, 5:55 PM

На сайте https://win-bee.pro/ вы сможете сыграть на реальные деньги и сорвать куш. И самое главное, что вас ожидает огромный выбор игр, которые созданы для проведения интересного и необычного досуга. Позвольте себе расслабиться и получить больше приятных эмоций от игры. И самое главное, что вы сможете воспользоваться огромным количеством бонусов, программой лояльности. Здесь всегда с особым трепетом и заботой относятся к игрокам, чтобы они не раз заходили на площадку. И самое главное, что игры, представленные здесь, намного выгодней, чем слоты.

Commenter Photo

omaicbob - Oct 5, 2022, 1:15 AM

На сайте https://zanex.ru/ вы сможете найти подходящий товар по более выгодной стоимости, чем в обычном магазине. Есть возможность сравнить цены, после чего подобрать наиболее доступный вариант по цене и условиям доставки. Почти все партнеры сервиса доставляют товары по России. Воспользуйтесь возможностью приобрести все, что нужно и в одном месте, потому как на сайте находятся более миллиона товаров, включая бытовую технику, электронику, все для строительства, аптеку, зоотовары и многое другое.

Commenter Photo

afacnsar - Oct 5, 2022, 1:36 AM

Картинки, раскраски, шаблоны, трафареты, поделки все это для развития вашего ребенка. Детям свойственно создавать что-то новое и необычное. Они легко двигаются вперед в плане развития и познания окружающего их мира. Помогите ребенку освоить творческое пространство с таким цифровым контентом. Из самой простой вещи ребенок может нафантазировать целый мир. Наш цифровой контент на сайте https://tozpat.ru/ помогает развить воображение вашего ребенка. Обеспечьте ребенка нашими бесплатными материалами для формирования нестандартного подхода, что требует любое творчество

New Comment