Showing posts with label ku pamięci. Show all posts
Showing posts with label ku pamięci. Show all posts

26/09/2014

Token Content in state Epilog would result in an invalid XML document

Home

To kolejny post z serii ku pamięci aby oszczędzić innym bólu. Otóż po wprowadzeniu zmian do logiki pewnego web service'u i napisaniu testów jednostkowych, postanowiłem go jeszcze przetestować integracyjnie przy pomocy skądinąd fajnego narzędzia SoapUI. Zacząłem od przygotowałem komunikatu XML do wysłania do usługi. Poszło szybko i myślałem, że to już prawie koniec mojej pracy. Niestety był to dopiero początek, gdyż okazało się, że po wysłaniu komunikatu serwer zwraca błąd jak poniżej:

Token Content in state Epilog would result in an invalid XML document.

Zdziwiłem się ponieważ to nie był pierwszy raz kiedy przechodziłem przez tą procedurę i nigdy z czymś takim się nie spotkałem. Początkowo pomyślałem, że to wina moich zmian, ale testy przy użyciu starej wersji kodu dały ten sam wynik. W następnej kolejności sprawdziłem, wiec czy używane przeze mnie wcześniej komunikaty/żądania dają ten sam błąd, ale działały poprawnie. W tym momencie wiedziałem już, że coś jest nie tak z tym konkretnym żądaniem. Zacząłem z niego wycinać kolejne elementy, aż pozostał prawie pusty, a błąd wciąż występował. W tym momencie mnie oświeciło i postanowiłem podejrzeć to czego nie widać gołym okiem czyli białe znaki. Kiedy to zrobiłem zakląłem szpetnie ponieważ przyczyną problemu okazał się znak nowej linii na końcu komunikatu - tuż po tagu zamykającym.

16/07/2014

LaTeX + PDF + obrazki

Home

Korzystając z LaTeX'a dokumenty PDF można tworzyć na przynajmniej dwa sposoby. Te znane mi to:
  • Pliki źródłowe *.tex -> dokument w formacie DVI -> PDF
  • Pliki źródłowe *.tex -> PDF
W pierwszym przypadku używamy dwóch programów tj. latex.exe oraz dvipdfm.exe, a w drugim tylko jednego tj. pdflatex.exe. Do tej pory stosowałem pierwsze podejście, ale w pewnym momencie chciałem skorzystać z szablonu, który był dostosowany do drugiego podejścia. I tu zaczęły się problemy, na których straciłem dużo czasu, a więc piszę ten post ku pamięci. Problemy te dotyczyły osadzania obrazków w dokumencie PDF.

Pierwszy problem polegał na tym, że kompilator krzyczał, że nie rozpoznaje rozszerzenia PS. To udało mi się przewalczyć w miarę szybko zmieniając rozszerzenia na EPS. Dziwne, ale zadziałało. Jakie było jednak moje zdziwienie kiedy po otworzeniu wygenerowanego dokumentu PDF nie znalazłem w nim żadnych obrazków, a dokładniej w miejscach przeznaczonych na obrazki widniały białe obszary o rozmiarze obrazków! Rozwiązanie okazało się jest dziwniejsze niż wcześniej. Otóż, wystarczyło z nazwy obrazka usunąć rozszerzenie czyli zamiast obrazek.eps wpisać obrazek.

Na tym nie koniec. Po jakimś czasie udało mi się doprowadzić do sytuacji kiedy obrazki były widoczne w dokumencie PDF zarówno kiedy nazwa zawierała rozszerzenie jak i bez niego. Otóż w celu umieszczenia w dokumencie obrazka w formacie JPG najpierw konwertuję go do formatu PS przy pomocy programu jpeg2ps.exe. Nie pamiętam już dlaczego, ale jpeg2ps.exe używałem z przełącznikiem -b. Nie wnikając w szczegóły do czego służy, po jego usunięciu problem ustąpił.

Mam nadzieję, że te krótkie wskazówki oszczędzą komuś czasu. Cały czas uważam, że LaTeX jest wspaniałym narzędziem, ale czasami potrafi doprowadzić do szewskiej pasji.

26/04/2014

Jeśli nie na tabela tymczasowa to co?

Home

W poście Quiz - coś do poduszki opublikowałem zestaw pytań z Quiz'u jaki zorganizowałem dla kolegów z pracy. Od czasu do czasu wpadają mi do głowy różne zagadki dlatego postanowiłem, że co ciekawsze będę wrzucał ku pamięci na bloga. Oto pierwsza z nich.

Po wykonaniu poniższego kodu na ekran zostanie wypisana wartość 0. Czego należy użyć zamiast tabeli tymczasowej aby aby na ekran została wypisana wartość 2?
CREATE TABLE #Temp (
Id INT IDENTITY,
Value VARCHAR(10)
);

BEGIN TRANSACTION;
INSERT INTO #Temp VALUES('aaa');
INSERT INTO #Temp VALUES('bbb');
ROLLBACK;

SELECT COUNT(1) FROM #Temp;

DROP TABLE #Temp;
Pokaż/Ukryj odpowiedź

Zamiast tabeli tymczasowej należy użyć zmiennej tabelarycznej.
DECLARE @Temp TABLE (
Id INT IDENTITY,
Value VARCHAR(10)
);

BEGIN TRANSACTION;
INSERT INTO @Temp VALUES('aaa');
INSERT INTO @Temp VALUES('bbb');
ROLLBACK;

SELECT COUNT(1) FROM @Temp;

06/04/2014

Zależności funkcyjne - kiedyś mnie tego uczono

Home

Ostatnia przeglądając pytania na stackoverflow.com natknąłem się na takie dotyczące wyznaczania kluczy głównych na podstawie zależności funkcyjnych. Uczono mnie tego na studiach, ale obecnie w praktyce tego nie stosuję i kiedy projektuję bazę danych to nie zaprzątam sobie tym głowy.

Pytanie skłoniło mnie  jednak do odświeżenia sobie wiedzy i sięgnąłem po klasykę w tej dziedzinie czyli "Systemy baz danych" Connollly'ego raz Begg'a. Po kilku minutach lektury okazało się, że w głowie pozostało więcej informacji niż się spodziewałem. Doszedłem jednak do wniosku, że może i zabawa z zależności funkcyjnymi jest dobra dla naszych szarych komórek, ale jednak jest to żmudny proces i fajnie by to zautomatyzować.

Trochę poszperałem w Internecie i znalazłem narzędzie dostępne on-line, które na podstawie zależności funkcyjnych wyznacza klucze kandydujące, weryfikuje w której postaci normalnej jest baza danych itp. Ma ograniczenia, ale zamieszczam link ku pamięci. A to dwa przykłady użycia tego narzędzi do rozwiązania pytań zadanych na stackoverflow.com:
A tak na marginesie. Czy w swojej praktyce zawodowej stosujecie lub znacie kogoś kto stosuje przy projektowaniu relacyjnych baz danych zależności funkcyjne i na tej podstawie sprawdza czy baza danych jest w odpowiedniej postaci normalnej?

29/03/2014

Słów kilka na temat Attach to Process

Home

Post z serii ku pamięci, o poleceniu Debug->Attach to Processz, które umożliwia podczepienie się pod już uruchomiony program i jego debugowanie, a które znane jest chyba wszystkim programistom pracującym z Visual Studio. Rzadziej stosowaną i znaną opcją Attach to Process jest możliwość wybrania rodzaju kodu jaki chcemy debugować (Native, Managed, Script...). Służy do tego okno Select Code Type, które pojawia się po wybraniu przycisku Select. Domyślnie typ kodu określany jest automatycznie i w większości wypadków jest to najlepsza opcja, można to jednak zmienić i wybrać debugowanie kodu na przykład tylko dla platformy .NET w określonej wersji.


Problem z tą opcją jest taki, że jak już się jej użyje to łatwo o tym zapomnieć,a Visual Studio zapamiętuje wybrane ustawienia. Załóżmy, że wybraliśmy debugowanie kodu zarządzanego w wersji 3.5. Wszystko fajnie działa, ale po paru dniach chcemy debugować kod dla platformy 4.0. Podczepiamy się pod wybrany proces, a tu nic się nie dzieje, żaden z naszych breakpoint'ów nie zadział, a Visual Studio nie zgłasza żadnych problemów.

I bądź tu mądry człowieku w takiej sytuacji, albo sobie przypomnimy, że zmieniliśmy tą opcję (o ile wiemy jak dokładnie działa) albo będziemy sobie rwać włosy z głowy.

27/01/2014

Ja vs Active Directory

Home

Od niedawna mam okazję pracować, przy pomocy API .NET'owego, z usługami katalogowymi w wydaniu Microsoft'u, czyli z Active Directory. Dla mnie nowa rzecz, więc z zapałem dziecka, które dostało nową zabawkę, zabrałem się do pracy i, jak to często bywa w takich sytuacjach, od razu napotkałem problemy właściwe dla początkujących. W ten sposób dowiedziałem się wielu rzeczy, które dla wyjadaczy mogą być oczywiste, ale dla mnie były nowością. Zebrałem więc je do kupy i tak powstała poniższa lista ku pamięci.

Niektóre z tych rzeczy to drobnostki i jeśli o nich zapomnimy nic wielkiego się nie stanie. Niektóre są jednak bardzo ważne i ich pominięcie może sprowadzić na nas większe kłopoty. Tego rodzaju rzeczy oznaczyłem jako [Ważne]

Projektowanie schematu
  • [Ważne] Przy projektowaniu schematu AD (definicja klas, atrybutów) trzeba być bardzo ostrożnym. AD nie wspiera usuwania klas lub atrybutów, a wiele rzeczy można zdefiniować tylko przy ich tworzeniu, na przykład atrybuty obowiązkowe dla danej klasy. AD wspiera natomiast tzw. dezaktywację. Ma to podobne skutki jak usunięcie, ale i tak wprowadzanie zmian do już używanego schematu AD może być bardzo kłopotliwe.
  • [Ważne] AD to nie C# i nie możesz sobie tak po prostu dodać nowego atrybutu do klasy i oczekiwać, że wszystkie jej instancje zostaną z automatu uaktualnione. Mam tutaj na myśli atrybut mustContain, który określa atrybuty obowiązkowe. Niestety, ale można go podać tylko przy tworzeniu danej klasy. Więcej ograniczeń znajdziecie tutaj.
  • Zamiast atrybutu mustContain można jednak użyć atrybutu mayContain, który określa atrybuty potencjalne.
  • Pisząc skrypt ldif definiujący nowy atrybut nie wystarczy użyć atrybutu attributeSyntax. Potrzebny jest jeszcze atrybut oMSyntax.
Limit 8KB
  • [Ważne] Ponownie AD to nie C#. Obiekty w AD nie mogą mieć więcej niż 8KB, a co za tym idzie, nie mogą zawierać dowolnej liczby atrybutów i wartości. Należy o tym pamiętać szczególnie, jeśli używamy atrybutów wielowartościowych. Ja analizowałem błąd, w którym nie można było dodać nowych wartości do atrybutu właśnie z tego powodu. Przekroczenie limitu 8KB dla danego obiektu skutkuje błędem Administrative limit for this request was exceeded
  • Aby było śmieszniej, nie można łatwo wyznaczyć maksymalnej dopuszczalnej liczby wartości, jakie zmieszczą się w danym atrybucie. Zależy to na przykład od tego, ile atrybutów ma dany obiekt. Ten artykuł zawiera fajną dyskusję praktycznych limitów na liczbę wartości w obiekcie. Sekcja Maximum Database Record Size
Atrybuty powiązane
  • Pewnym rozwiązaniem problemu ograniczonej wielkości obiektów są tzw. atrybuty powiązane (ang. linked attributes), w których zawartość jednego atrybutu zależy od zawartości innych obiektów. Problemem jest natomiast to, że taki wyliczany atrybut musi być typu distinquished name, a więc nie obsłużymy w ten sposób np.: listy liczb całkowitych.
  • [Ważne] Jeśli atrybuty mają być powiązane to muszą być takie od początku.
  • Działanie atrybutów powiązanych może nie być intuicyjne, a więc załączam poglądowy schemat. Jak widać atrybuty połączone to para atrybutów tzw. forward link oraz backward link. Backward link przechowuje wskazania na obiekty, które wskazują go w atrybucie forward link.


Stronicowanie
  • AD ma ograniczenie na liczbę obiektów, jakie można pobrać z bazy w jednym zapytaniu. .NET pozwala to jednak bardzo łatwo obejść dzięki stronicowaniu. Należy ustawić właściwość DirectorySearcher.SizeLimit na 0, a właściwość DirectorySearcher.PageSize na wartość inną niż 0. Nic więcej nie trzeba robić. Więcej szczegółów tutaj.
  • [Ważne] Domyślnie .NET nie używa stronicowania. Jeśli o ty zapomnimy, może dojść do sytuacji, kiedy nasz program nagle przestanie działać, bo nie będzie pobierał wszystkich oczekiwanych obiektów z AD.
    Inne
    • [Ważne] Klasy z przestrzeni nazw System.DirectoryServices, takie jak DirectorySearcher, DirectoryEntry, SearchResultCollection implementują interfejs IDisposable. Piszę o tym ponieważ nawet przykłady na MSDN nie biorą tego pod uwagę!
    • Skrypt ldif, służy do wprowadzania zmian do AD i składa się z sekwencji operacji dodania, usunięcia lub zmodyfikowania czegoś. W przypadku operacji modyfikacji (changetype: add) na końcu powinien znaleźć się znak „-“.
    • Uwaga na spacje w atrybucie cn. Mój skrypt ldif dodający do schematu nowy atrybut wywalił się, bo wartość dla atrybutu cn zawierała na końcu spacje.
    • AD ma różne limity ograniczające, na przykład maksymalna liczbę wartości, jakie można pobrać, maksymalną wielkość strony itp. Pełną listę można znaleźć tutaj.
    Lista ta z pewnością nie jest kompletna. Jeśli macie jakieś sugestie to chętnie ją rozszerzę.

    19/07/2011

    See[Mike]Code

    Home

    Dzisiaj rozmawiając z kolegami zeszliśmy na temat rekrutacji programistów. Między innymi rozmawialiśmy o narzędziach wspomagających ten proces takich jak Codility. Rozmowa ta przypomniała mi, że swego czasu natknąłem się ba bardzo proste ale pomysłowe narzędzie pozwalające na żywo, zdalnie sprawdzić jak potencjalny kandydat radzi sobie z programowaniem. Miałem trudności z przypomnieniem sobie adresu strony dlatego ku pamięci publikuję ten post. Przy okazji sądzę, że narzędzie to może przydać się innym. Mianowicie chodzi o See[Mike]Code.

    Zasada działania jest bardzo prosta. Wchodzimy na stronę See[Mike]Code, klikamy przycisk New Interview Site i otrzymujemy dwa adresy. Jeden wysyłamy do kandydata, a drugi zachowujemy dla siebie. O wyznaczonej porze prosimy aby kandydat uruchomił przeglądarkę i wszedł na podany adres. Jego oczom ukarze się taki widok:



    Kiedy wejdziemy pod drugi adres wyświetlona zostanie dość podobna strona. Teraz prosimy kandydata aby wykonał jakieś proste zadanie programistyczne np.: słynne FizzBuzz, a jego poczynania możemy obserwować na ekranie naszego komputera. See[Mike]Code nie udostępnia takich dobrodziejstw jak IntelliSense ale w przypadku prostych zadań, takich jak wspomniane FizzBuzz, nie jest to konieczne.

    Jestem przekonany, że na polskim rynku nie mamy sytuacji, w której jak to napisał Jeff Atwood na swoim blogu:

    Like me, the author is having trouble with the fact that 199 out of 200 applicants for every programming job can't write code at all. I repeat: they can't write any code whatsoever.

    Sądzę jednak, że dobrze mieć w swoim repertuarze takie narzędzie.

    14/04/2011

    CURRENT_USER , SYSTEM_USER...

    Home

    W poście Problem z domyślnym schematem wspomniałem, że w celu wyjaśnienia problemu posłużyłem się funkcją CURRENT_USER, która zwraca nazwę bieżącego użytkownika. Czym jednak funkcja ta różni się od funkcji SYSTEM_USER, SESSION_USER czy innych o podobnych nazwach. Sprawa jest prosta. Część z tych funkcji zwraca login, który służy do uwierzytelnienie się względem serwera, a część nazwę użytkownika, która określa co możemy zrobić w ramach poszczególnych baz danych (autoryzacja). Każdy login jest skojarzony (zmapowany) z jednym użytkownikiem dla danej instancji bazy danych. Nie jest to nic skomplikowanego ale można się zgubić w gąszczu nazw. Dlatego ku pamięci, głównie dla siebie, zebrałem te informacje w postaci poniższej tabelki.

    CURRENT_USERZwracają nazwę użytkownika
    USER_NAME
    SESSION_USER
    USER

    SYSTEM_USERZwracają login
    SUSER_SNAME

    Więcej szczegółów np.: parametry wywołania, wyjaśnienie skąd wzięło się tyle funkcji robiących to samo, można znaleźć tutaj.